home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-01 | 138.4 KB | 4,623 lines |
- Far from being complete, but it is a beginning ...
-
-
- /**************************************************************\
- * *
- * F68K *
- * *
- * *
- * Technical Reference Manual *
- * *
- * *
- * last change: 06-24-91 *
- \**************************************************************/
-
-
- Content
-
- F68K copyright notes
- Introduction
- Forth-83?
- Loader
- Input and output
- Mass storage
- Pointer and addresses
- Header
- USER variables
- Values and locals
- Vocabularies
- Interpreter
- Control structures
- Reducing the kernel
- F68K streaminterface
- Lineeditor
- Fullscreen editor (not longer provided)
- F-EDIT
- Possible errors
-
- Documenation of loader implementations
- Atari ST
- Sinclair QL
- Commodore Amiga
-
- Glossary
-
-
- ###############################################################
- F68K COPYRIGHT NOTES
- ###############################################################
-
-
-
- F68K was created to support distribution of the FORTH
- programmimg language. So there are only shareware-fees on F68K
- for PRIVATE use. You are free to make, use and give away copies
- of F68K, as long as the author's names are left visible, and
- this file comes to the new user, too.
-
-
- ****************************************************************
- Important!!!
- ****************************************************************
-
- F68K will never be ready. It shall develop continously. So there
- is no version number of the whole system, but only of the
- kernel. Your version should be 1.0.
-
- F68K is NOT thought to be a system which is ready to use on all
- levels and all computers. It shall be as large and universal as
- it can be at a time, but not more. In order to make it larger
- and more universal, F68K needs YOUR help. So, if you have ported
- F68K to a new hardware or have written a new tool or an
- application, which can be of interest to other users, please
- send it to me. I will find an appropriate place of your part in
- the system and add your name to the F68K-programmers list you
- find below.
-
- ****************************************************************
-
-
-
- The F68K-kernel is COPYRIGHTED. While using F68K you accept my
- ownership.
-
-
- Copying Fees
-
- If you normally charge a fee for making someone a copy of a
- disk, you may charge the same fee for making a copy of F68K. The
- fee must be based solely on the cost of making the copy, and
- must be the same fee that you charge for a copy of any other
- disk.
-
-
- Licensing
-
- If you develop soft- or hardware that uses the F68K-kernel and
- wish to SELL your product along with F68K, please get in touch
- with me so we can work out a licensing agreement. The
- F68K-kernel may not be sold as part of any system without a
- licensing agreement. I'll be willing to work out an agreement
- that is fair to both of us.
-
- If you do not want to sell anything together with F68K, but
- nevertheless like it, please contact me or the 'Forth
- Gesellschaft e.V.' in order to come to know the latest news on
- F68K. Send me some (at least two) ST or DOS formatted disks and
- a paid envelop with your address on it, I will register you and
- send you the latest version of F68K at all times. If the disks
- are not formatted or the envelop is missing, I will just keep
- the rest.
-
- Please understand that I cannot give away the entire kernel
- listing with this free version of F68K. If you are REALLY
- interested in that listing, please contact me and we will find
- an appropriate agreement.
-
-
-
- Documentation
-
- As said above, F68K will never become ready. So documentation
- will never be ready, too. You will always find some essential
- documentation on the disks in the '.TXT' files and within the
- sources, of course. If you would like to have the latest version
- of documentation, see 'Licensing'.
-
-
- Liability
-
- I shall have no liability or responsibility to any person or
- entity with respect to any loss or damage caused or alleged to
- be caused directly or indirectly by F68K. This includes, but is
- not limited to, any interruption of service, loss of business,
- loss of information or that which is rendered inaccurate, or
- loss of anticipated profits or ANY OTHER CONSEQUENTIAL OR
- INCIDENTAL DAMAGES RESULTING FROM THE USE OF F68K, even if I
- have been advised of the possibility of such damages.
-
-
-
- Acknowlegdement
-
- I am grateful to J. Staben for many hours of discussion on FORTH
- specific problems. Thanks to the members of the local group
- RHEIN/RUHR of the 'Forthgesellschaft e.V.' for fruitful
- discussion of technical details.
-
-
- My address:
-
- Dipl. Phys. J. Plewe
- Grossenbaumer Str. 27
- D-4330 Muelheim/Ruhr
- Germany
- Tel.: 0208/423514
-
-
-
- You also can get copies from:
-
- FORTH-Gesellschaft e.V.
- Postfach 1110
- D-8044 Unterschleissheim
- Germany
-
- or from anyone, who is willing to make you a copy
-
-
-
- ---------------------------------------------------------------
- These people worked at F68K (Hall of Fame)
-
- J. Plewe F68K kernel, kernel extensions
- Laxen & Perry M68000 Assembler
- Hartwig Luedemann L&P assembler on 32 bit
- Dirk Kutscher Sinclair QL loader
- Markus Redeker Lots of bugs and tools, F-EDIT
- Reinhard Scharnagl Disassembler
- Wolfgang Schemmert Amiga loader
- Thomas Beierlein OS9 loader
- ---------------------------------------------------------------
-
-
-
-
- Hope you enjoy the system,
- keep going forth, your's
-
- J. Plewe
-
-
-
-
-
- P.S. If you miss a message like 'If you like ... please send $xx
- to ...' here is one for you:
-
- You may support me and F68K by sending any amount of money!!
-
-
-
-
-
-
-
-
- ###############################################################
- Introduction
- ###############################################################
-
- FORTH is a widespread computer language that has been
- implemented on nearly all important machines. If you have got a
- PC, than you will be able to choose your system out of a set of
- highly developed FORTH implementations. If you have one of the
- less often sold computers, such as Mac, ST or Amiga this is true
- to some degree, too.
-
- Now FORTH is a language, who's applications typically do NOT run
- on such machines, but on single-chip or home-build computers,
- for example.
-
- This is because FORTH does not care for operating systems or
- complicated I/O. It may be easily be run on a naked system. In
- those cases, everyone has to develop his own FORTH environment.
- F68K wants to close this gap between the commonly used and the
- 'special' systems.
-
- F68K was designed to run on ALL MC68000 computers without
- changing and recompiling or reassembling the kernel. For that
- reason, the kernel may not depend on the I/O or the address
- configuration of the target system. In order to achieve that,
- without trying miracles, there will have to be a loader for each
- machine or operating system. This loader 'knows' all the machine
- dependent stuff.
-
- Porting F68K to a new computer means to create a suitable
- loader. Because all loaders are similar, this is an easy task.
- An experienced programmer might do that before breakfeast.
-
- So, if you have just build a new MC68000 system, you will
- immediately be able to use the tremendous power of a unique
- FORTH programming environment.
-
-
-
- ###############################################################
- Forth-83?
- ###############################################################
-
- F68K follows the FORTH-83-standard in most cases, but it cannot
- be a real FORTH-83 system at all, because it uses a 32 bit
- stack. In some details it leaves FORTH-83 and turns towards the
- new ANSI standard, which is not completely defined yet. So the
- words COMPILE and [COMPILE] no longer exist. They have been
- replaced be the more smart POSTPONE.
-
- The old words are easily redefined:
-
- : COMPILE POSTPONE POSTPONE ; IMMEDIATE
- : [COMPILE] POSTPONE POSTPONE ; IMMEDIATE
-
-
- There are slight deviations concerning control structures. See
- the corresponding chapter "Control Structures" for details.
-
- The most important deviation is the expansion of blocksize to
- 2kB. This gives the user a full 80x25 screen for source editing
- (see "Mass storage") and allows the creation of an internal
- forth filesystem, called FIFI. This is described in the chapter
- "F68K streaminterface".
-
- It is intended that F68K shall develop towards ANSI, although
- the dpANS standard defines a block to be of a size of 1024
- bytes. But for F68K blocks are of 2000 bytes, almost any ANSI
- compatible source will compile and run correctly, even if some
- bytes (2000- 1024) perhaps will be wasted.
-
-
-
- ###############################################################
- Loader
- ###############################################################
-
-
- The F68K system consists of an F68K system image and a loader,
- which has to load the system image into memory and to provide it
- with all necessary I/O- and memory information.
-
- So it becomes possible to design the system image to be
- perfectly independent of any hardware and/or operating system.
-
- Porting F68K to a new system or even a completely new hardware
- means to create the appropriate loader and the system will run.
- Of course, the loader has to fit the system, so one has to
- follow some rules when creating the loader.
-
-
- What the loader does
-
- The task of the loader is quite simple: it has to install the
- code and the data part of the system image into memory, invent
- some good addresses for the stacks and the TIB (Terminal Input
- Buffer) and to store all these addresses in a given structure
- together with the (absolute) addresses of the I/O functions and
- to push the address of this structure on the returnstack,
- indexed by the address register A7. It then simply has to jump
- to the start of the code segment. That's all!
-
-
-
- Loading the system image
-
- As said above, the system image consists of two parts: a code
- and a data segment. Both must be loaded into memory before the
- system is ready to run. This action depends on the way, the
- system image is stored on the mass storage device or ROM. In all
- cases, it must be known, how these parts can be placed in
- memory. For example, in the original distribution, the image was
- created with an assembler under the operating system GEMDOS on
- Atari ST. So, there is an image file that consists of the code
- and data parts and a file header. In that header, which is 28
- byte large, one will find with an offset of two the length of
- the code segment and with an offset of six the size of the data
- segment:
-
- struct header
- {
- int magic;
- unsigned long codesize;
- unsigned long datasize;
- int dont_care[9];
- } header;
-
-
- In the original distribution, the integer 'magic' holds the two
- characters 'JP', which are the initials of my name. So the
- loader has the possibility to check wether the given imagefile
- contains a valid F68K image.
-
- One will have to load the header, fetch the named values and
- then load the two parts into appropriate buffers. If the system
- comes in an other form, these informations must be given, too.
- The buffers, of course, have to be larger than the sizes of the
- segments. In most cases, a buffer of 64 kbyte for code is
- enough. For the data segment, no limit can be predestined.
-
-
-
- I/O functions
-
- There are five functions, that must be given by the loader:
-
- getting a character from the terminal, KEY
- getting the terminal's status, KEY?
- putting a character to the terminal, EMIT
- reading an writing blocks from/to the
- mass storage device, R/W
- ------------------------------------------------
- reading data from a system dependent device
- writing F68K data to a system dependent device
-
-
- There is a defined data interface of these functions to F68K.
- They all find theire parameters on a stack indexed by the
- address register A7, which is the standard F68K returnstack.
- They all leave outcoming parameters in the dataregister D0. Note
- that this data interface is the same used by common C-compilers,
- where parameters are passed on the returnstack (A7). This makes
- it very simple to write a loader in C. When using assembler
- language, it is important to know, that the parameters lie on
- the stack in reverse order to those on the F68K-stack! On the
- top of returnstack there always is the returnaddress. There is a
- simple translation from F68K-parameters to stack positions:
-
-
- Forth: ( para1 para2 para3 -- ret )
- Stack (a7): 4(a7) 8(a7) $c(a7) d0
-
-
- So this interface is easy-to-use even on assembler level.
-
- The loader can define more then one routine for all six
- functions. E.g. it can submit an EMIT for a terminal, a printer,
- a serial port and a file. There may be functions for a KEY which
- comes from the terminal or the serial line (not from the
- printer, of cource). There has to be a table for each of the six
- functions which has to be constructed as follows:
-
-
- byte 0-3: number of routines
- byte 4-7: first routine
- byte 8-11: second routine
- . .
- . .
- . .
-
- Example:
-
- keytable: DC.L 2
- DC.L TERMKEY
- DC.L SERIALKEY
-
-
- The addresses of theses tables are later passed to F68K. They
- can be accessed on FORTH-level using the words KEYS, KEY?S,
- EMITS, R/WS, READSYSES and WRITESYSES. They give the address of
- the 0. byte of the appropriate table. The first entry of each
- table will be taken as the default I/O. So there is an easy way
- to support all I/O devices available and to redirect I/O on
- FORTH-level:
-
-
- : >PRINTER ( -- ) KEYS 2 CELLS + @ ^KEY ! ;
-
-
-
- Here is a description of the I/O functions and theire parameters
- in detail. The user has not to care about registers and the F68K
- stack. F68K saves all registers before calling the loader's
- functions and sets the datastack to the right value after
- return.
-
-
- a.) KEY
-
- KEY does not expect any parameter. It just waits for the
- terminal to send a character. This character is embedded as the
- least significant byte of long word (4 byte) and then pushed
- onto the stack.
-
- example:
-
- KEY: JSR get_key ;the character comes in D0
- RTS
-
- or
-
- long key()
- {
- return (long)getch();
- }
-
-
-
- b.) KEY?
-
- KEY? does not expect any parameter. It checks the terminal,
- wether there is a character available for KEY. In that case, it
- returns a TRUE flag (something <>0), otherwise a FALSE flag in
- register D0.
-
-
- example:
-
- KEY_QUEST: JSR termstate ;status comes in D0
- RTS
-
- or
-
- long key_quest()
- {
- return (long)kbhit();
- }
-
-
-
- c.) EMIT
-
- EMIT takes a character from the stack and prints it on the
- terminal. Some terminal emulation can be done here. After EMIT,
- there is no parameter on the stack.
-
-
- example:
-
- EMIT: MOVE.L 4(A7),D0 ;SP: return char
- JSR char_out ;print the character
- RTS
-
- or
-
- void emit(c)
- long c;
- {
- putch((char)c);
- }
-
-
-
- d.) R/W
-
- R/W is the most complex function of these four. It has three
- parameters on the stack. First, there is a flag, wether reading
- (flag = 0) or writing shall be performed, then there is the
- blocknumber and the last parameter is the (absolute) address of
- a buffer. When the flag is zero, then the block with the given
- number has to be loaded into the buffer at the given address. If
- the flag is something unequal to zero, then the data in the
- buffer at the given address has to be written into the given
- block. A block is an amount of 2048 byte = 2 kB on the mass
- storage device. There are always 2048 bytes read or written.
- Where they come from or where they go to only concerns to the
- R/W function. F68K does not care! Because errors may occur
- during load or save, R/W leaves a flag in register D0, which is
- nonzero in case of success.
-
-
- example:
-
- *Forth parameters ( buffer block r/w? -- flag )
- *stack position 4(a7) 8(a7) $c(a7) d0
- * 0(a7) is returnaddress
- R_W: TST.L $C(A7) ;read or write?
- BEQ read_block
- write_block: MOVE.L 8(A7),D0 ;get block number
- ASL.L #2,D0 ;512 byte/sectors
- MOVE.L #4,D1 ;number of sectors
- MOVE.L 4(A7),A0 ;the buffer
- JSR write_sectors ;flag in D0
- RTS
- read_block: MOVE.L 8(A7),D0 ;get block number
- ASL.L #2,D0 ;512 bytes/sector
- MOVE.L #4,D1 ;sectors to be read
- MOVE.L 4(A7),A0 ;the buffer
- JSR read_sectors ;flag in D0
- RTS
-
- or
-
- long r_w(buffer, block, rwflag)
- long buffer, block, rwflag;
- {
- if(rwflag==0)
- return diskread(buffer, block);
- /*not shown here*/
- else
- return diskwrite(buffer, block);
- /*not shown here*/
- }
-
-
-
- Note that blocks must not be physical blocks on a floppy or
- harddisk. They can also be emulatet, for example, within
- streamfiles provided by an operating system.
-
-
-
- e.) READSYS
-
- READSYS allows the user to read F68K data from the system, which
- loaded F68K. In general, this will be a file in an operating
- system. This path is installed in order to be able to design a
- unique and system independent import function e.g. for sources
- in F68K. READSYS gets a buffer's address and the length of the
- buffer as arguments. If succesful, it returns -1=TRUE, otherwise
- 0=FALSE.
-
-
- example:
-
- *Forth parameters: ( addr count -- flag)
- *stack positions: 4(a7) 8(a7) d0
- READSYS: TST.L FIRST
- BNE NOOPEN
- MOVE.L FILENAME,A0
- BSR OPENFILE
- MOVE.L D0,INHANDLE
- NOOPEN: MOVE.L 4(A7),A0 ;BUFFER
- MOVE.L 8(A7),D0 ;COUNT
- JSR FREAD
- MOVE.L 8(A7),D1 ;COUNT again
- CMP.L D1,D0 ;error?
- BEQ NOERROR
- CLR.L D0 ;FALSE-flag
- BRA RSYSEND
- NOERROR: MOVE.L #-1,D0 ;TRUE-flag
- RSYSEND: RTS
-
- or
-
- long readsys(buffer, count)
- {
- static int first;
- static int inhandle;
-
- if(first) fopen(&inhandle,"INFILE"); /*or so*/
- return (fread(inhandle,buffer,count) == count);
- }
-
-
-
- f.) WRITESYS
-
- WRITESYS allows the user to write F68K data to the system, which
- loaded F68K. In general, this will be a file in an operating
- system. This path is installed in order to be able to design a
- unique and system independent SAVESYSTEM function in F68K. But
- WRITESYS can also be (mis)used for other purposes, e.g. output
- protocols or export of sources. WRITESYS gets a buffer's address
- and the length of the buffer as arguments. If succesful, it
- returns -1=TRUE, otherwise 0=FALSE.
-
-
- example:
-
- *Forth parameters: ( addr count -- flag)
- *stack positions: 4(a7) 8(a7) d0
- WRITESYS: TST.L FIRST
- BNE NOCREATE
- MOVE.L FILENAME,A0
- BSR CREATEFILE
- MOVE.L D0,OUTHANDLE
- NOCREATE: MOVE.L 4(A7),A0 ;BUFFER
- MOVE.L 8(A7),D0 ;COUNT
- JSR FWRITE
- MOVE.L 8(A7),D1 ;COUNT again
- CMP.L D1,D0 ;error?
- BEQ NOERROR
- CLR.L D0 ;FALSE-flag
- BRA WRSYSEND
- NOERROR: MOVE.L #-1,D0 ;TRUE-flag
- WRSYSEND: RTS
-
- or
-
- long writesys(buffer, count)
- {
- static int first;
- static int outhandle;
-
- if(first)
- fopen(&outhandle,"OUTFILE"); /*or so*/
- return (fwrite(outhandle,buffer,count) == count);
- }
-
-
-
-
- Using different devices with R/W
-
- In some cases there may be more than one blockoriented device.
- If so, R/W has to multiplex the different devices. For that
- reason, a set of block ranges for each device has to be
- declared. For example, there are a floppy drive and a harddisk
- and the floppy gives room to 320 blocks. Then the following
- table, called ROOTTABLE has to be allocated in the loader:
-
-
- DC.L 2 ;there are two devices
- DC.L 0 ;floppy uses blocks 0-319
- DC.L 320 ;capacity is 320 blocks
- DC.L 320 ;block >320 are on harddisk
- DC.L 1000 ;capacity of harddisk is 1000 blocks
-
-
- In dependency of the blocknumber, the function used by R/W now
- has to switch between different access mechanisms, for example
-
- R_W: IF blocknumber < 320
- THEN access floppy
- ELSE access harddisk
-
- The word ROOTTABLE in F68K is a constant whih gives the pointer
- to roottable. There is a USER-Variable called ROOTBLK, which is
- added to the number given to BLOCK, before BLOCK uses R/W. So
- the user may define simple words, which switch between he
- devices.
-
- For example:
-
-
- : D0: ROOTTABLE 4 + @ ROOTBLK ! ;
- : D1: ROOTTABLE 12 + @ ROOTBLK ! ;
-
- When F68K is initialised, the first entry in the roottable is
- written to the variable ROOTBLK, so this is an easy way to take
- one device as default.
-
-
- Buffers in memory
-
- F68K needs at least five addresses of buffers in memory which
- have to be allocated by the loader. First there are the two
- buffers for code and data segments. Second, there is need for at
- least two buffers for the data- and the returnstack. Last, a
- buffer for the TIB must be available. The allocation of these
- buffers may be done according the taste of the programmer or the
- needs of the application.
-
- Here are some hints:
-
- The TIB must not be smaller than 256 bytes. It may be larger but
- there is no need for a larger buffer in standard cases.
-
- The stacks grow towards lower addresses, whereas TIB grows to
- higher addresses. So the same pointer may be used as a base for
- one of the stacks (usually the datastack) and the TIB. When the
- F68K dictionary is expanded, it gros towards higher addresses in
- code and data segment. It it a good advice to place the stacks
- at the end of availible memory and the code and data segments at
- the beginning.
-
- Here is a possible memory map as an example:
-
-
- lowest address (la): start of code segment
-
- .
- .
- .
-
- la + 64kb: return stack base
- start of data segment
- .
- .
- .
- .
- .
-
- ha - 256 byte: start of TIB, data stack base
- .
- highest address (ha): end of TIB
-
-
-
- As an second example, one could make the TIB buffer larger an
- place the returnstack at the end of TIB, so it grows towards
- start of TIB.
-
-
- Note that F68K does NO error checking concerning stack or
- dictionary overflows!
-
-
-
- Starting F68K
-
- When the I/O functions are written, the memory is allocated and
- the system image is loaded, F68K can be started. The necessary
- parameters, which are all known now, have to be stored into a
- structure shown below which address' has to be pushed on the
- returnstack. Then the jump into the system can be performed.
-
-
- forthparas:
- registers: DS.L 16 ;d0,d1,d2,d3.......,a5,a6,a7
-
- data: DS.L 1
- code: DS.L 1
- datstk: DS.L 1
- retstk: DS.L 1
- TIBptr: DS.L 1
- codelen: DS.L 1
- datalen: DS.L 1
- emittable: DS.L 1
- keytable: DS.L 1
- keyqtable: DS.L 1
- r_wtable: DS.L 1
- readsystable: DS.L 1
- writesystable: DS.L 1
- roottable: DS.L 1
- ;extensions like files, grafics, windowing can be placed here
-
-
- or
-
-
- struct forthparas
- {
- long registers[16]; /* to be filled by F68K */
- void *data;
- void *code;
- void *datstk;
- void *retstk;
- void *TIBptr;
- long codelen;
- long datalen;
- void *emittable;
- void *keytable;
- void *keyqtable;
- void *r_wtable;
- void *readsystable;
- void *writesystable;
- void *roottable;
- /* possible extensions like files, grafics, windowing */
- } forthparas;
-
-
-
-
- Example:
-
- MOVE.L databot,data ;start of data segment
- MOVE.L codebot,code ;start of code segment
- MOVE.L tib,datstk
- MOVE.L retstack,retstk
- MOVE.L tib,TIBptr ;same pointer for stack an TIB
- MOVE.L #$20000,datalen ;data segment's size is 128 kb
- MOVE.L #$10000,codelen ;code segment's size is 64 kb
- MOVE.L #EMITTABLE,emit
- MOVE.L #KEYTABLE,keytable
- MOVE.L #KEY_QUESTTABLE,keyqtable
- MOVE.L #R_WTABLE,r_wtable
- MOVE.L #READSYSTABLE,readsystable
- MOVE.L #WRITESYSTABLE,writesystable
- MOVE.L #ROOTTABLE,roottable
-
- MOVE.L forthparas,-(A7)
- JSR codebot ;jump into the system, MUST be JSR
-
- BRA exit ;when come back, then exit loader
-
-
- (retstack, tib, databot and codebot shall be variables with the
- pointers to returnstack, the TIB, the start of data and code
- segments, respectivily)
-
-
- or
-
-
- set_forthparas();
- f68k(forthparas);
-
-
-
- Hopefully, F68K will prompt now with it's 'ok'!
-
-
- The forthparas are visible from F68K simply using FORTHPARAS.
- This gives access to the functiontables, that may be added at
- the end of the structure. So there is a very flexible
- possibility to extend the F68K loaderinterface e.g. for special
- abilities of operating systems. There is no standardisation yet,
- but I would suggest to reserve the first free place for a
- pointer to a table of file functions, the next for grafics and
- the third for windowing. The first implementation of one of
- these, which reaches me, could set the standard, e.g. the F68K
- standard GEM interface.
-
-
- There are some very important things to say about the
- 'registers' area in the forthparas. The reader should have
- noticed, that this area is not influenced by the loader. Indeed,
- this area will be filled by F68K itself during initialisation.
- All regsiters of the loaders runtime environment will be stored
- here in the following order:
-
- D0, D1, .... D7, A0, A1, .... A7
-
- The value for A7 in this area (registers + 15*4) will be of the
- location pointed to before F68K has been called. That means that
- the top of this A7-stack will point to the forthparas. This
- gives the possibility for the I/O-functions to restore theire
- runtime environment completely, including the returnstack. This
- can make sense, when the I/O-functions need some registers,
- which the loader has saved on the loaders returnstack for them.
- They can be accessed by the pointer held within 'register'. The
- I/O-functions must take care that the original A7 (that is used
- by F68K) will be restored before returning to F68K.
-
-
- !!! Important !!!
-
- Some critical operating systems need a specific set of register
- contents to execute the loaders I/O-functions. F68K saves these
- registers in the FORTHPARAS-structure as described above. In
- order to make this area accessible to the loader functions, F68K
- places the absolute address of the FORTHPARAS in bottom of the
- (return-)stack, below the parameters. I/O-functions in those
- critical environments therefore have the possibility to restore
- vital registers and then execute the appropriate I/O-function.
- In uncritical environments, one not has to take care about this
- value on the stack, because it will be removed automatically
- when returnig control to F68K.
-
-
-
-
-
- ###############################################################
- Input and output
- ###############################################################
-
- All of the F68K in- and output functions are vectorized. The
- addresses of the I/O functions are held in the USER-variables
- (KEY), (KEY?), (EMIT), (R/W), (READSYS) and (WRITESYS),
- respectivily. The appropriate words KEY, KEY?, EMIT, R/W,
- READSYS and WRITESYS always use these vectors. These Variables
- are preset with the addresses of the F68K-words LOADERKEY,
- LOADERKEY?, LOADEREMIT, LOADERR/W, LOADERREADSYS and
- LOADERWRITESYS.
- These words again only use vectors for execution. These are
- ^KEY, ^KEY?, ^EMIT, ^R/W, ^READSYS and ^WRITESYS. If the F68K
- startup routine held in the USER-variable (COLD) does not change
- one of these variables, then they will be filled with the first
- of the addresses provided in the loader's I/O function tables
- (see 'Loader') at system's entry. The user may store other
- addresses fetched from these tables or completely new I/O
- functions in these variables. When doing this, he should know
- about some dependencies.
- It is important that the addresse held in ^KEY, ^KEY?, ^EMIT,
- ^R/W, ^READSYS and ^WRITESYS point to functions provided by the
- loader. The must not be executed in F68K simply using EXECUTE.
- The system may crash. These functions may only be called using
- LOADERKEY, LOADERKEY?, LOADEREMIT, LOADERR/W, LOADERREADSYS and
- LOADERWRITESYS because some interfacing concerning the
- parameters has to be done. On the other hand no simple F68K-word
- may be stored in these vectors or the same reason.
-
- The words EXPECT or TYPE use the lower level functions KEY and
- EMIT. So if KEY is changed, all words using KEY, like EXPECT,
- will be changed, too. So KEY influences even the input editor.
- If the user wants to avoid this, he will be able to change
- EXPECT and TYPE, too. They are vectorized with the
- USER-variables (EXPECT) and (TYPE).
-
-
-
- ###############################################################
- Mass storage
- ###############################################################
-
-
- F68K supports mass storage devices like floppies and/or
- harddisks. For F68K has to be a portable system, the mass
- storage support must be portable, too. This is only possible
- when NOT using existing file systems or other access mechanisms
- on F68K level.
-
- F68K accesses the mass storage device in portions of 2 kb = 2048
- bytes. This quantity is called a BLOCK. Each block has a unique
- number. The range of this number does not depend on F68K, but on
- the implementation of the read/write primitive in the loader
- (see 'Loader').
-
- When refering a specific block by it's number, e.g.
-
-
- 27 BLOCK ( blocknumber -- address )
-
-
- F68K finds an appropriate buffer using the word BUFFER and then
- passes the buffer's address and the number of the block to the
- word R/W, which then calls the read/write function in the
- loader. R/W can be seen as the end of the mass storage interface
- on the side of the device, whereas BLOCK is the end on the side
- of F68K. BUFFER than is something like a tunnel between the
- ends.
-
- According to the stack comment for BLOCK, it expects a block
- number and returns a address. This address points to the buffer,
- where the data of the block was read in. Writing to a block
- means writing into that buffer. If the buffer is marked as
- changed, using the word UPDATE, it will be written back to disk
- again when the buffer is used for another block or the user
- executes FLUSH, which saves all UPDATE'ted buffers to disk. But
- in the normal case, the user does not have to take care wether
- is block is read from or written to disk. The user may access
- mass storage in the same way as he does with memory. So, the
- F68K blocks are a kind of virtual memory.
-
- Although the physical size of a block on a disk is 2 kb (often
- four sectors), the size of a buffer is only 2000 bytes. This is
- because the first 48 bytes of each block are used for internal
- management of blocks. The user may access these 48 bytes by
- using negativ offsets on the address returned by BLOCK, but he
- should be very carefull. By the way, the reserved bytes will be
- used, for example, to realize block organisation on a disk, so
- that streams of blocks may be refered by name, in a way it is
- done with files on 'normal' operating systems.
-
- So 2000 bytes of data may be used freely.
-
-
-
- Handling Buffers
-
- In a virtual memory system, buffers have to be handled. The
- buffers are the connection between virtual and real memory.
- Buffer handling in F68K is performed by the word BUFFER:
-
-
- BUFFER ( blocknumber -- address )
-
-
- Every F68K system must have at least one buffer, but any other
- number is possible, too. More buffers cause less disk activity.
-
- A F68K buffer has the following structure:
-
- 14 bytes header
- 2048 bytes block data
-
- in detail:
-
- $0 pointer to next buffer
- $4 physical number of block in the data buffer
- $8 logical number of block in the data buffer
- $C UPDATE flag
- $E data buffer, 2048 bytes
-
-
- All buffers used by F68K are linked together in a cyclic linked
- list. The first four bytes of a buffer are used for the
- necessary pointer. There is a USER-variable called PREV, which
- contains a pointer to the buffer most recently refered.
-
- The second four bytes contain the number of the block which has
- been refered. This is the number which is passed to R/W when
- reading or writing the block. In contrast, the number in the
- third entry in the buffer's header is a logical blocknumber. It
- is only used when using a 'higher' disk organisation, where the
- disk is divided into several streams of blocks. Then this number
- may be the logical number of a block within such a stream. Last
- there is a word (2 bytes) which is used as a flag, wether the
- block has been altered after loading from disk.
-
- When the user executes BLOCK or BUFFER, then a new buffer has to
- be allocated. The mechanism to do that is quite simple.
- Bufferallocation is always done with BUFFER. BLOCK calls BUFFER
- itself. BUFFER expects a blocknumber on the stack. Now, first it
- checks, wether the refered block is already loaded in one of the
- existing buffers. The word ?CORE does this check. For all
- buffers are linked in a cyclic list, ?CORE starts with the
- buffer the USER-variable PREV points to, and compares the number
- on the stack with the second value in the buffers header. On
- equality, ?CORE stops returning the buffer's address, otherwise
- it fetches the link to the next buffer until it reaches the
- buffer it started with. If no equality has occured, it returnes
- a FALSE- flag. If ?CORE does not result in FALSE, BUFFER simply
- returns the buffer ?CORE found. If ?CORE could not find a buffer
- containing the data of the desired block, BUFFER will use the
- buffer following the one, which PREV points to. But before
- returning the address of that buffer, it first checks the
- UPDATE-flag in the header. If it is set, the buffer is written
- back to disk to the block that is indicated by the physical
- blocknumber in the header. It then clears the UPDATE-flag and
- writes the address of that buffer to the USER-variable PREV. Now
- the buffer is allocated and BLOCK may load it's data into it
- using R/W.
-
- The sense of this mechanism becomes clearer when observing the
- chronological order in which buffers are used. When taking the
- next buffer in the cyclic linked list, it is clear, that this
- one is the 'oldest' among all buffers. It is a natural aim to
- use the buffer, which is the at least recently used. This is
- perfectly done by this mechanism.
-
-
- Notes
-
- All which is said above is valid when using the kernel directly.
- BLOCK and BUFFER are DEFERred words, which may be redirected
- e.g. by the blockstream system. The description above is meant
- for the primitives (BLOCK and (BUFFER, which are originally used
- by BLOCK and BUFFER.
-
- There is another technical detail to be mentioned. To simplify
- access, BLOCK first compares the given blocknumber, which it
- converts into a physical blocknumber by adding ROOTBLK, with the
- content of the global variable LASTBLK. If they are identical,
- BLOCK returns with the content of LASTBUF. Otherwise the way
- described above is gone and LASTBLK and LASTBUF are updated
- accordingly.
-
-
- ###############################################################
- Pointer and addresses
- ###############################################################
-
-
- This chapter is very important, because F68K distinguishes
- between two types of pointers or addresses. In general, all
- addresses are relativ! There is no occasion in F68K, where
- absolut addresses are used.
-
- In most cases, the user has not to care for address handling. He
- may use the '@' and '!' operators as usual.
-
- There are some very special situations, where the user has to be
- careful. These situation occur, when addresses of executable
- code, e.g. addresses within the code segment, occur.
-
- Then the user has to remember, that F68K consists of two
- segments: the code- and the datasegment.
-
- 'Normal' addresses, which may be operands to '@' and '!' are
- always offsets into the datasegment. That is clear, because the
- user normally wants to access data, not code.
-
- So, if the user defines a variable,
-
-
- VARIABLE X
-
-
- then a header and space for the data is allocated within the
- datasegment, whereas the runtimecode of VARIABLE is located in
- the codesegment. X gives the offset of the data within the
- datasegment on the stack. So '@' or '!' work with these offsets.
-
- Now consider the following problem:
-
- The user wants to compile some words 'by hand', so he has to get
- the appropriate codeaddress and to compile it.
-
- Here is a somewhat unusual version of ': NIP SWAP DROP ;'
-
-
- : NIP ( n1 n2 -- n2 ) [ ' SWAP JSR, ' DROP JSR, ] ;
-
-
- This version compiles a different code than the natural one.
- This comes from the fact, that F68K internally does not use
- 'JSR,' for codegeneration. As indicated by the name, it only
- generates a JSR-code and does not care for relativ branches or
- macro expansion ('JSR,' generates an additional MOVE-operation,
- which is of no interest in this context. 'JSR,' generates code
- of a defined length, which can be useful sometimes).
-
- In fact, F68K uses the word 'COM,' for codegeneration. The word
- ' (tick) gets the address of the following word in form of an
- offset into the CODEsegment. So no '@' or '!' is possible with
- that address!! 'JSR,' knows this fact and it is only natural,
- that words, which generate code, use addresses out of the
- codesegment.
-
- But for 'COM,' there is a difficulty: it should know wether the
- word to be compiled has to be expanded as a macro. The
- corresponding information is located in the control word in the
- header of that word. But the header is in the DATAsegment! So
- 'COM,' needs the address of the word's header. This address is
- found using the word H' (header tick):
-
-
- : NIP ( n1 n2 -- n2 ) [ H' SWAP COM, H' DROP COM, ] ;
-
-
- In order to make the relation between ' and H' clearer, one may
- express ' by H':
-
-
- : ' ( -- addr ) H' @ ;
-
-
-
- Addressconversion between segments
-
- There are some other occasions, where the user wants to access
- data within the codesegment. E.g. he wants to access the value
- of a variable without using the variable's name (for what
- reason?). Then he has to know something about a variables
- structure, which is the same for all CREATE structures. In the
- codesegment, there is the runtime-code of a variable. It is the
- code generated by 'JSR,' (see 'Generating Code'), that means,
- that there are 8 bytes of code for each variable. Behind these 8
- bytes there is a pointer to the data. This pointer is
- datasegment-relative, of course. But the pointer itself is in
- the codesegment, so it has to be accessed there. For that
- reason, one has to define a word, which transforms a
- codesegment-relative into a datasegment- relative address:
-
-
- : CODE>DATA ( Caddr -- Daddr ) SYSBOT + $8000 + ;
-
-
- SYSBOT is a constant that gives the address (datasegment-
- relative) of the beginning of the codesegment. The $8000 has to
- be added because the codeaddresses are relative to the middle of
- the first 64k-codesegment (see 'Generating Code' again). Now the
- variables data can be accessed:
-
-
- VARIABLE X
-
- ' X ( pointer to runtimecode of a CREATE-word )
- 8 + ( pointer now behind runtimecode )
- CODE>DATA ( make it relative to datasegment ... )
- @ ( so @ can get the pointer to the data )
- @ ( now gets the value )
-
-
- By the way, 'X @' does the same and is a bit less complicated.
-
-
-
- Converting from/to absolute addresses
-
- In some cases it could be necessary to obtain the absolut
- address from a relativ. This could be useful in writing
- CODE-definitions. This conversion is done with the word
-
-
- >ABS ( reladdr --- absaddr )
-
-
- So '0 >ABS' gives the absolute start of the datasegment. To
- convert codesegment relativ addresses, there is the word
- >ABSCODE. '0 >ABSCODE' gives the absolute location of the
- codesegment.
-
- When using machinecode in CODE-definitions, two addressing modes
- are defined to simplify access to F68K data and code. These are
- DATA) and CODE), which have to be pronounced 'datasegment
- indirect' and 'codesegment indirect', respectivily. Theire usage
- is simple:
-
-
- Variable X
-
- CODE X@
- ' X # d0 .l move \ get pointer to X in codeseg
- 8 # d0 .l addq \ put it behind code
- d0 code) d0 .l move \ get pointer to data
- d0 data) sp -) .l move \ get data
- next end-code
-
-
- This is the same way to access a variables value as it was used
- in the example above in high-level. It is important, that the
- register holding the F68K-address is a dataregister d0-d7!
-
-
- Last, there should be the possibility to access absolute
- addresses, that means to convert an absolute address into an
- relative F68K-address. This is performed with the word
-
-
- (ABS) ( absaddr -- reladdr )
-
-
- So '0 (ABS) @' reads the absolute address 0 (and gives the reset
- SSP). (ABS) and >ABS are reversing each other.
-
- Corresponding to (ABS) there is (ABSCODE) which converts an
- absolute into a codesegment relative address.
-
-
- !!!! Important Rule: If a location in the datasegment is
- referenced, the pointer must always be relative to the
- datasegment. If a location in the codesegment is referenced, the
- pointer must always be relative to the codesegment. NEVER
- compile a reference to codesegment as an pointer relative to
- datasegment! If a conversion (CODE>DATA) has to be made, it
- ALWAYS has to be made a runtime!
-
- Example: accessing the VIEW-information in the codesegment
-
-
- : TEST
- ... ['] A_WORD CODE>DATA 4- @ ... ;
-
-
- is correct, but
-
-
- ... [ ' A_WORD CODE>DATA 4- ] LITERAL @ ... ;
-
-
- is WRONG.
-
-
- If you wonder why, remember that code- and datasegment may be
- placed anywhere in memory. So it is not possible to fix a
- location in the codesegment with an address relativ to the
- datasegment. If the segments will be placed somewhere else the
- next time, the intersegment-relative pointer will probabely have
- wrong values!! Think of it!
-
-
- '>R', 'R>' and 'R@'
-
- Additionally, something very important has to be said about the
- words '>R', 'R>' and 'R@'. In traditional implementations, these
- words simply push, pop or fetch a word from/to the datastack
- to/from the returnstack. In F68K, this words do some conversion
- with the data while moving between the stacks. When pushing
- something to the returnstack, it is always treated like an
- address and it is converted into a absolute machineaddress. This
- has to be done because this should be possible:
-
-
- : FOO ['] FOO1 >R ;
-
-
- The codeaddress of 'FOO1' is pushed onto the returnstack, so
- that it will be executed when reaching the 'RTS' instruction
- compiled by ';'. For the M68000 does not know anything about
- F68K pointer- treatment, the address on top of the returnstack
- has to be a valid machineaddress. So the conversion from a F68K
- codesegment relative address (permitted by '[']') into an
- absolute address is performed by '>R'. So '>R' implicitely uses
- '>ABSCODE'. This has to be reconverted, if the data returns from
- the returnstack. So 'R>' and 'R@' implicitely use '(ABSCODE)'.
- For this reason it is not allowed to push something onto the
- returnstack using '>R' and later get an explicite access using a
- sequence like
-
-
- RP@ @
-
-
- because the reconversion is omitted in this case. A legal
- sequence to do things like that is
-
-
- RP@ @ (ABSCODE) \ do the right conversion
-
-
- doing the conversion 'by hand'.
-
- This highly compatible use of of '>R', 'R>' and 'R@' has to be
- paid with a little more effort accessing inline-data in the
- codesegment. Inline-values normally are accessed using the top
- of returnstack as a pointer to the value. For now this pointer
- is an absolute machineaddress, it has to be converted before
- access using '@' can be performed. There are two possibilities
- to do that. They are very hard to explain, so I let an example
- do the explanation:
-
-
- : GETINLINE ( -- N )
- R@ >ABSCODE (ABS) \ convert address
- \ RP@ @ (ABS) \ ... this is more simple
- @ \ access inline-data
- \ R> 4+ >R ; \ increase returnaddress
- 4 RP@ +! ; \ ... or this way
-
-
- : TEST ( -- 27 )
- GETINLINE [ 27 CODE, ] ;
-
-
- Note that 'CODE,' has to be taken to create the inline-data
- instead of ','.
-
-
-
-
- ###############################################################
- Header
- ###############################################################
-
-
- Each word defined in F68K is preceeded by a header. This header
- contains information about the name of the word, the location of
- the code and some flags. Additionally, all headers of one
- vocabulary (see 'Vocabularies') are linked together as a long
- chain of words. Each header holds a pointer to the header last
- defined before (in the same vocabulary). The structure of a
- header is very simple:
-
-
- -----------
- | Control | \ 16 bit
- =====================
- | Ptr to code | 'CFA' \ 32 bit
- =====================
- | Ptr to last header| 'LFA' \ 32 bit
- =====================---------------------
- | Cnt| Name of word as counted string ...|
- ------------------------------------------
-
-
- In the controlword, some bits have a special meaning:
-
- Bit 0: the word is SMUDGE. The vocabulary searching word FIND
- will ignore words with this bit set. REVEAL will set this bit to
- zero.
-
- Bit 1: the word is immediate. When compiling, this word will
- be executed, nevertheless.
-
- Bit 2: the word is restrict. This means that this word must
- not be executed interactivily. It can only be used in the
- compiling state (STATE=-1).
-
- Bit 3: the word is a macro. This bit will be set, when the
- word has successfully been compiled using the defining words
- 'M:' or 'MCODE'. When the F68K-macrooption is on (MACRO ON),
- then the F68K-compiler will not compile a reference to this
- word, but will copy the complete code.
-
-
- Bits 8-15: in this byte the length of the code is stored.
- This number is measured in 16bit. The final RTS-instruction at
- the end of the code is not counted. This number is important for
- F68K-macrocompiler.
-
-
- The pointer to code holds the 32bit-address of the code. It is
- called the 'CodeFieldAddress' or 'CFA'. This is the address
- given by the word ' ' '. This address is already relative to the
- codesegment, so '@' or '!' must not be used with this address!
- (If you wonder why, remember that code- and datasegment may be
- placed anywhere in memory. So it is not possible to fix a
- location in the codesegment with an address relativ to the
- datasegment.) One longword before beginning of code, there is
- the VIEW-field. This field contains a 32bit-value, which is the
- number of the physical sourceblock, where this word has been
- defined. The VIEW-field was placed by the code instead by the
- header because so it will be possible to find the source again,
- even when the header has been removed or destroyed. To access
- this number, a source sequence like this is necessary:
-
-
- ' A_WORD CODE>DATA \ find codeaddress an convert it
- 4- @ \ fix pointer to the 32bit-word
- \ before the code and fetch the
- \ VIEW-information
-
-
- Be carefull not to compile the address of the VIEW-field after
- conversion (CODE>DATA). Conversions have to be done at runtime!!
- (see: 'Pointer and Addresses')
-
-
- The next field contains the pointer to the last recently defined
- header (in the same vocabulary). It is called the
- 'LinkFieldAddress' or 'LFA'. This is an ordinary F68K-pointer
- (relative to datasegment). This link is used when searching in
- the vocabulary. The LFA of the first word in each vocabulary is
- NULL (0).
-
- After the linkfield there is the name of the word preceeded by a
- countbyte. This name is a standard FORTH-string.
-
-
-
- ###############################################################
- USER variables
- ###############################################################
-
-
- FORTH passes it's parameters on a stack. This is the 'normal'
- procedure. But sometimes it is usefull to have some 'real'
- variables, which can be refered by name, equal to variables used
- in other languages. They are declared in most cases with the
- defining word VARIABLE.
-
- But since FORTH is a multitasking, sometimes multiuser system,
- this datatype cannot be used in all situations. VARIABLEs can be
- changed by all tasks and users. So no task or user can rely on
- the content of a variable. If a variable has to be bound to only
- one task or user, it has to be defined using the defining word
- USER.
-
- USER-variables are all stored together in one field. The size of
- that field is determined by the kernel and now is 2 kbyte. There
- are about 300 bytes used by the kernel itself, so there is romme
- enough. When creating a USER-variable, the offset of the first
- free entry in the USER-area is stored together with the header
- of the defined word. The access occurs with this offset together
- with a pointer to the base of the USER-area. The pointer is
- always held within the machine-register D5. Switching this
- register to another USER-area means to switch all
- USER-variables. Each task has it's own USER-area, so it may
- change these variables without taking effect on other tasks.
-
- There are some memory buffers connected to a task, which may not
- be shared with others. These is e.g. the vocabulary stack. In
- order to allow an automatical allocation of all these buffers
- when creating a new task, F68K provides a simple mechanism: all
- these buffers are organized in a linked list. Behind the pointer
- for the link there will be the length of the buffer in bytes.
- The address of the first element of that list is stored in he
- USER- variable USERBUFS. So it is very easy to allocate all
- necessary buffers.
-
- Hint:
- Sometimes it is necessary to put even the block buffers into
- this list. This depends on the nature of the taskswitcher
- (interruptive or cooperative). The one and only buffer provided
- with the kernel has two longwords in front of it left empty, so
- that is possible without taking completely new buffers.
-
-
-
- ###############################################################
- Values and locals
- ###############################################################
-
-
- F68K provides two types of data, which are not common to all
- FORTH implementation, but will be fixed in the coming ANS-
- standard. These are VALUE and LOCAL, which are similar in
- implementation and usage:
-
-
- <n> VALUE <name>
-
- <n> LOCAL <name>
-
-
- VALUE and LOCAL create an initialised datatype, which behaves
- just like a constant. So
-
-
- 27 VALUE FOO
- FOO . --> 27
-
-
- In contrast to simple constants, VALUEs and LOCALs are changeble
- using the prefix 'TO'. So
-
-
- 35 TO FOO
- FOO . --> 35
-
-
- This is the same with LOCAL.
-
-
- LOCAL differs from VALUE, of cource. LOCAL can only be used
- within ':'-definitions and creates a local value, which is
- visible just before the next ';' is compiled.
-
-
- : ADD ( a b -- a+b )
- LOCAL B LOCAL A
- A B + ;
-
- B --> unknown!
- 3 5 ADD . --> 8
-
-
- To see how LOCALs can be changed, here a somewhat silly example:
-
-
- : ADD2 ( a b -- a+b )
- 0 LOCAL A 0 LOCAL B
- TO B TO A
- A B + ;
-
-
- By the way, the best and fastest way to define 'ADD' in F68K is
-
-
- MACRO @ MACRO ON
- M: ADD ( a b -- a+b )
- + ;
- MACRO !
-
-
- So 'ADD' is as fast as '+' itself.
-
-
- LOCALs are very useful when there are a lot of parameters on the
- stack or when parameter handling is difficult. The use of LOCALs
- in definitions like 'ADD' should be avoided, because they use a
- lot of memory and time.
-
- The use of VALUEs instead of VARIABLEs is strongly recommended,
- because they are faster and need less memory. Often, the syntax
- becomes clearer. The user should not use VALUEs where a CONSTANT
- would do the job, too, because nothing is shorter and faster
- then a CONSTANT.
-
-
- Implementation
-
- VALUE and LOCAL both create same code. LOCAL produces an extra
- call to allocate the memory for the data. Both use an in-line-
- address to find the data. VALUE creates the following code:
-
-
- +--------------+-----------------+-------------+
- | CALL fetcher | in-line-address | CALL storer |
- +--------------+-----------------+-------------+
-
-
- It is important, that the fetcher is compiled using a 'JSR,' so
- that the 'CALL fetcher' always uses 8 bytes.
-
- The in-line-address points to the data for VALUEs and to a
- pointer to the data for LOCALs. The difference is due to the
- fact, that this pointer for a LOCAL has to be modified at
- runtime, and so it has to be fixed, when the code segment is
- placed in ROM. The pointer holds a fixed address of a location
- in the data segment, where the pointer to data will written at
- runtime (the data segment may not be in ROM).
-
- The task of the fetcher is to get the in-line-address and to
- fetch the data from there. When referencing or compiling the
- VALUE, always the fetcher is used. It is 'TO', which activates
- the storer. 'TO' finds the codeaddress of the following VALUE-
- type using `'`, adds an offset of 12 bytes (8 byte 'CALL
- fetcher', 4 byte in-line-address) and executes or compiles this
- address itself, corresponding the content of the USER-variable
- STATE.
-
- The storer then gets the in-line-address from in front of it's
- call and stores the data on the stack in this location.
-
- LOCAL additionally compiles a 'CALL initer' in front of the
- sequence above. This 'initer' links 4 bytes off the returnstack,
- initialises this place with the value from top of stack and
- pushes the address of a routine on the returnstack, which
- unlinks the allocated space on the returnstack at exit-time.
- This is very complicated to explain, although it is very simple.
- The user should take a glance at the sources. There are only a
- few lines of assembler in the kernel.
-
-
- Restrictions
-
- Some little restrictions occur when using LOCALs. The user
- should be very careful manipulating the returnstack. Defining a
- local means to alter the first two elements on returnstack.
-
-
- : TEST
- ... \ something
- >R
- 0 LOCAL TEMP \ never!
- R> \ never!
- ... \ something further
- ; \ crash!
-
-
- One could use
-
-
- R> R> R> SWAP >R SWAP >R
-
-
- instead of 'R>', but this should be avoided for reasons of
- readability.
-
-
-
- ###############################################################
- Vocabularies
- ###############################################################
-
-
- F68K supports a vocabulary structure, which allows usage of same
- namens for different words. Vocabularies are lists of words
- compiled into them. There is a search order of vocabularies,
- which is followed when F68K tries to find a word extracted from
- the source. When the user has created words with the same name
- in different vocabularies, F68K will take the first one it
- finds, e.g. the one within the vocabulary, which is the highest
- in the search order. The gives the possibility to compile
- different version of a word just by installing a appropriate
- search order. Applications should always have an own vocabulary
- and sub- vocabularies, they are hierarchic, so that the
- applications words can easily be seperated from the words inside
- the development environment. The main vocabulary of the
- environment is called FORTH. System words like DUP, ROT or
- FORGET are located in that vocabulary.
-
-
- Usage
-
- Vocabularies are created using the defining word VOCABULARY
- followed by the desired name e.g.
-
-
- VOCABULARY FOO
-
-
-
-
-
- Implementation
-
- The implementation had to be somewhat complicated, in order to
- preserve the ROMability of the code segment.
-
- Vocabularies consist of a normal header, which may be deleted
- when headers are removed, too, and a set of pointers in both,
- code and data segment.
-
-
- There first is the runtime code of a vocabulary with a fixed
- length of six bytes (JSR <32b-address>) in the codesegment. Then
- there is a pointer (ptr1) to a field in the data segment, which
- is normally located behind the header of the vocabulary. This
- pointer (ptr3) contains the address of the link field of the
- last word in the vocabulary. Behind this pointer there is a
- second one (ptr4) which points back into the code segment. It
- points to the location just behind the runtime code, where the
- pointer (ptr1) into data segment is. So code and data segment
- are linked forth and back in a vocabulary.
-
- Vocabularies themselves are linked together with a pointer
- (ptr2) which is located with an offset of 8 behind the
- runtimecode. The last element of the vocabulary list can be
- found in the USER- variable VOC-LINK. It is important to know
- that this pointer gives addresses within the codesegment, so '@'
- cannot be used. The user has to apply 'CODE@' instead.
-
-
-
- CODE DATA
-
- +--> ptr2 of former vocabulary
- |
- |
- | JSR dovoca header
- | ptr1 ---------------------------> ptr3 -----+
- | ^--------------------------- ptr4 |
- +---ptr2 |
- |
- |
- |
- last header <+
-
-
-
-
- ###############################################################
- Interpreter
- ###############################################################
-
- The subroutine INTERPRET to be decribed here is normally called
- the 'outer interpreter' to make clear that there is an inner
- interpreter as well. For F68K does not have any inner
- interpreter because it creates native code, this distinction has
- not to made here.
-
- The F68K interpreter is invoked using the word INTERPRET. This
- will interpret or compile the strings given by WORD until WORD
- will return the address of a string which will cause NULLSTR? to
- answer with true. This will be the case when the input stream,
- coming from the terminal or a block, is exhausted. INTERPRET
- could be implemented in the following manner:
-
-
- : INTERPRET ( -- )
- BEGIN
- BL WORD NULLSTR?
- WHILE
- PARSER
- REPEAT ;
-
-
- As it can be seen, PARSER will do most of the work consuming the
- input. PARSER is a DEFERred word which can either compile or
- interpret the strings supplied by WORD. This depends on wether
- the actual state of the system (STATE) is compiling (STATE<>0)
- or interpreting (STATE=0). In the first case, PARSER will
- execute COMPILER, in the latter it will execute INTERPRETER. The
- switch between this to words for PARSER is done by the words '['
- and ']' which are implemented like that:
-
-
- : [ ( -- )
- 0 STATE ! ['] INTERPRETER IS PARSER ;
-
- : ] ( -- )
- -1 STATE ! ['] COMPILER IS PARSER ;
-
-
- INTERPRETER and COMPILER each take the address of the next
- string in the input stream as an input parameter and do both
- yield no output parameter:
-
-
- COMPILER ( addr -- )
- INTERPRETER ( addr -- )
-
-
- This implementation makes it possible to use the interpreter
- itself for applications just by replacing the word executed by
- PARSER.
-
- A simple example for that is to list all words that would have
- been isolated by WORD on the terminal instead of really
- interpreting them:
-
-
- : PRINTER ( addr -- )
- COUNT TYPE CR ;
-
-
- : :LIST ( n -- ) \ <n> :LIST
- ['] PRINTER IS PARSER
- LOAD
- ['] INTERPRETER IS PARSER ;
-
-
-
- or to show extended use of DEFER-words:
-
-
- : :LIST ( n -- ) \ <n> :LIST
- ['] PARSER CELL+ CODE@ PUSH \ save runtime of PARSER
- ['] PRINTER IS PARSER
- LOAD ;
-
-
-
-
-
- ###############################################################
- Control structures
- ###############################################################
-
- F68K provides control structures, which are identical to those
- used in FORTH-83 systems in most cases. But in some points, F68K
- turns to the new ANSI standard. This concerns the
- BEGIN..WHILE..REPEAT(UNTIL)-structure. In F68K, any amount of
- WHILEs are allowed, but there must be a THEN for each additional
- WHILE behind REPEAT in order to resolve the references left open
- by WHILE. It is also possible to use WHILEs together with AGAIN
- or UNTIL, but there has to be a THEN for each WHILE. This gives
- the structure some more flexibility, for there may be code
- between UNTIL and THEN:
-
-
- ... BEGIN ... WHILE ... WHILE ... UNTIL ... THEN ... THEN
-
-
- It seems to be clear, that a REPEAT can always be replaced by
- 'AGAIN THEN' with the additional possibility to place code
- between AGAIN and THEN.
-
-
- The other structures behave as usually. The following structures
- are available:
-
-
- IF ... (ELSE) ... THEN
- BEGIN ... AGAIN
- BEGIN ... WHILE ... REPEAT
- BEGIN ... WHILE ... (WHILE) ... REPEAT ... (THEN)
- BEGIN ... WHILE ... AGAIN ... THEN
- BEGIN ... (WHILE) ... UNTIL ... (THEN)
- DO ... LOOP
-
-
- The word LEAVE is used to leave a DO...LOOP. EXIT is forbidden
- between DO and LOOP because DO...LOOP holds some parameters on
- the returnstack. ANSI says there has to be a word UNLOOP which
- removes these parameters, so 'UNLOOP EXIT' should be possible.
-
-
-
- ###############################################################
- Reducing the kernel
- ###############################################################
-
- When using F68K on little machines, where not mass storage
- device is connected and memory is spare, then it can be usefull
- to cut off some words concerning mass storage from the kernel in
- order to save memory. This incudes the one diskbuffer installed
- in the kernel. So there is the possibility to save more than 2kB
- of expensive memory. Here it is:
-
-
- ' UPDATE FENCE ! \ set FENCE a bit lower
- FORGET UPDATE \ and forget the word before diskbuffer
-
-
- From now on, no UPDATE, (LOAD or LOAD will be available and
- there will be no buffer for the BLOCK- and BUFFER-words. BLOCK
- and BUFFER assume that there always is at least one buffer. For
- this is not the case now, it should be strictly avoided to use
- these words. The result would be unpredictable.
-
- Sources, of course, now only can be typed in by hand or been
- downloaded from a server.
-
-
-
-
- ###############################################################
- The F68K streaminterface
- ###############################################################
-
- 'Normal' computers have 'normal' interfaces for using files on
- mass storage devices. For F68K is a very special thing, it
- follows, that is must have a very special fileinterface.
-
- Speaking more exactly, it is not a real fileinterface, because
- it does not interface commonly known files. 'Files' in F68K are
- a concatenation of blocks. So they are called BLOCKSTREAMS. It
- is a blockstream interface to be described here.
-
- I want to replay briefly the ideas, that lead to such an
- interface:
-
- First I was discontented with the too small editing area when
- using the classical 1k-blocks. I wanted to use my full 80x25-
- screen to write my sources. So for 80x25 make 2000 characters, I
- had to take 2k for a block, because no mass storage device I
- know allows the usage of 2000 bytes as a blocksize (not in a
- simple manner). So there they are, 48 unused bytes. That nearly
- broke my heart. As pain makes creative, there quickly came the
- idea to use these 48 bytes to design a simple file-, sorry,
- blockstreaminterface. The blocks just had to be linked together
- forward and backward and some blocks had to used as directories.
- That's all! So far history, now the present.
-
- The interface was designed to be loaded immediately on the
- kernel. So no sophisticated FORTH-features could be used. The
- imagefile created with the streaminterface loaded should be used
- as the new kernel.
-
- The 'normal' block management words like BLOCK or LOAD exist
- within blockstreams, too. So the user does not ave to learn a
- new block handling. '1 LOAD' will load the first block as it
- ever does, but now the first block is not the first block on a
- disk, e.g. first track, first sector, but the first block within
- a blockstream. There no longer is a dependency of the
- blocknumber used on high level F68K and the physical blocknumber
- given the the R/W primitive.
-
- A blockstream is a simple bidirectional linked list. The first
- longword within the unlucky 48 bytes of a physical block
- contains the physical blocknumber of the following block. The
- second longword holds the preceeding. If there is no following
- or preceeding, for all blockstreams have a beginning and an end,
- these longwords will enumerate to '-1'. Behind these two
- longwords, there is a 16-bit statusword, which decides about the
- type (data, directory,..., see below) of this block. So 10 Bytes
- of the wasted diskspace are used now.
-
- Here is the first important note: the first block has the number
- '1', not '0'. This was done because in a blockstreamsystem that
- contains a lot of blockstreams, there are a lot of first block,
- of course. Due to the fact, that block '0' cannot be loaded
- using the word LOAD, this would create a lot of unusable blocks
- of 2k each. I dont like to waste anything.
-
-
- Here is the structure:
-
-
-
- | block 1 |
- +--->|--------------|
- | | |----+
- | |--------------| |
- | | -1 | |
- | +--------------+ |
- | |
- | | | block 2 |
- | +--->|--------------|<---+
- | | | |
- | |--------------| |
- +-----------------------------| | |
- +--------------+ |
- |
- .
- .
- .
- .
- | block n | |
- |--------------| |
- | -1 | |
- |--------------| |
- | |-----------------------------+
- +--------------+
-
-
-
- Only the actual block in use 'knows' where to find the following
- or the preceeding block. The blockstream's information is stored
- locally. There is no need for something like a FAT (File
- Allocation Table) as a globally known place where all
- informations about files are stored.
-
-
- This has many advantages:
-
- - it fits to the problen. The unused 48 bytes are local
- storage capacity and can therefore only be used in a local
- context.
-
- - it is very save. When working with FATs the destruction of
- the physical location on the device, where the FAT is stored, is
- a fatal and unrecoverable error. Destroying local information
- only causes local damages, which can be recovered sometimes.
-
- - it is completetly independent from any device specific
- characteristics. F68K does not care for the nature of the
- device.
-
- - very large devices can be managed. About 2^31 2k-blocks are
- a lot of storage capacity.
-
- - it is simple.
-
-
- But it has disadvantages, too:
-
- - it is NOT very fast. Especially in large blockstreams of
- some hundreds of blocks it is a hard job to find a block with a
- high number when a block with a low number was used last. All
- blocks between them will have to be read. One can work around
- this disadvantage using short blockstreams and many buffers.
-
-
- Each blockstream has a unique name. These names are stored in
- special directory blocks. Each directory entry holds the name,
- the length and the physical number of the first block of a the
- corresponding stream. Additionaly there is a status word. This
- status words decides wether the described blockstream is a
- 'normal' blockstream containing user data or a directory again.
- Hence, the directory structure is hierachic. The user can build
- tree-like directories as they are used within other filesystems,
- too.
-
- The physical block 0 of each device will be a directory block,
- the so called rootdirectory.
-
-
- An entry in a directory block describing a blockstream has
- following simple structure:
-
-
- +---------------------------------------------------+
- |name of blockstream, max 30 characters|frst|len |st|
- +---------------------------------------------------+
- ^ ^ ^
- | | |
- phys. number of first block ---------+ | |
- | |
- length of blockstream --------------------+ |
- |
- status: 0=datastream, 1=directory ------------+
-
-
- For each entry needs 40 bytes, one directory block can hold 50
- entries. If more entries are needed, then a directory consists
- of more than one block, which are organized like datastreams.
- Expansion of a directory occurs automatically, the user does not
- have to take care.
-
-
-
- Implementation
-
- The implementation of the words that are needed to handle
- blockstreams are divided into two levels. First there is a set
- of words which can be used in :-definitions and have something
- of the character of an operating system call.
-
- Second there is a set of words wich can be used typing shell
- commands. The second level depends on the first.
-
-
- The words of the second level will probably be used first, so
- they are decribed first. All words here allow the usage of
- pathnames. A pathname is a list of directories and
- subdirectories which all must exist. The names of the
- directories are seperated by '/'-characters. If the first
- character of a pathlist is a '/', too, then the path is searched
- beginning from the root directory. Otherwise search starts in
- the actual directory.
-
- Example: suppose the user to be in the directory MYDIR. In this
- directory there is a subdirectory called YOURDIR. Then
- '/MYDIR/YOURDIR/TESTSTREAM' and 'YOURDIR/TESTSTREAM' refer to
- the same blockstream.
-
- This a common syntax in many operating system so no further
- description about pathname is given here.
-
- Different devices can be accessed via the pathname putting the
- devicenumber and a colon in front of a pathlist. No slash is
- allowed behind the colon, or the device is ignored.
-
- '1:MYDIR/TEST' will take the stream TEST from device 1 in the
- path '/MYDIR/' whereas '1:/MYDIR/TEST' will search the actual
- device. So for other devices than the current always the
- complete pathname has to be given!
-
-
-
- MOUNT ( -- ) usage: MOUNT
- This will initialise a blockstream system copied to a device.
- For directories contain physical blocknumbers, they are not
- portable to other devices, where other blocknumbers are used.
- MOUNT makes the blockstream system fit to the actual device.
- Note that only a system, that has been UNMOUNTed, can be
- mounted. Always make sure that you are working with MOUNTed
- systems only. Oterhwise malfunction is guaranteed. It is not
- possible to doubly MOUNT a system.
-
-
- UNMOUNT ( -- ) usage: UNMOUNT
- This will prepare a blockstream system to be copied to an other
- device. From all physical blocknumbers contained in the system,
- the number of the first physical block on the actual device will
- be substracted. A later mount will reverse that procedure.
- Always make sure that you are working with MOUNTed systems only.
- Oterhwise malfunction is guaranteed. It is not possible to
- doubly UNMOUNT a system.
-
-
- MAKE ( -- ) usage: MAKE <name>
- This will create a blockstream with length 1 in store it into
- the actual directory or in the directory given together with
- <name>.
-
-
- USE ( -- ) usage: USE <name>
- This will open the blockstream with the name <name> for usage.
- Now the words BLOCK, LOAD or BUFFER refer to that blockstream. A
- STREAM: structure called USESTREAM will be filled with the data
- about the selected stream.
-
- Notice that if a blockstream has been created with MAKE, then
- USE must be supplied additionally.
-
-
- DEL ( -- ) usage: DEL <name>
- This will delete the blockstream with the given name. If the
- stream has former been USEd, the F68K word created there will
- not be deleted!
-
-
- MORE ( n -- ) usage: <n> MORE
- This will extend the blockstream which is currently in USE by n
- further blocks. They will be appended to the end of the stream.
-
-
- LESS ( n -- ) usage: <n> LESS
- This will reduce the blockstream currently in USE by n blocks.
- They will be taken from the end of the stream.
-
-
- INSERT ( where amount -- ) usage: <where> <amount> INSERT
- This will insert <amount> blocks at the position <where> in the
- blockstream.
-
-
- EXPEL ( where amount -- ) usage: <where> <amount> EXPEL
- This will cut <amount> blocks out of the current blockstream.
- The block <where> will not be cut, it remains in the stream. To
- remember this, remember that the first block of a stream cannot
- be EXPELled. E.g. 3 2 EXPEL will cut the block 4 and 5 from the
- stream.
-
-
- MAKEDIR ( -- ) usage: MAKEDIR <name>
- This will create a subdirectory with the given <name>.
-
-
- DELDIR ( -- ) usage: DELDIR <name>
- This will delete a directory. Notice that this directory has to
- be empty, e.g. it may contain nor streams neither directories,
- otherwise an error condition exists.
-
-
- CD ( -- ) usage: CD <name> or CD
- This will change to the directory given in <name>. If no <name>
- is given, then the actual directory path is printed on the
- terminal.
-
-
- DIR ( -- ) usage: DIR
- Shows the content of the current directory.
-
-
- DIRECT ( -- ) usage: DIRECT
- Switches the blockstreamsystem of. Now BLOCK, LOAD and BUFFER
- access the physical blocks again. The variable ROOTBLK is
- deleted.
-
-
- STREAMS ( -- ) usage: STREAMS
- Invokes the blockstreamsystem. Now BLOCK, LOAD and BUFFER access
- the logical blocks within the system. The variable ROOTBLK is
- cleared and has not to be changed!
-
-
-
- On the other hand, there are a lot of low-level functions. Some
- of them correspond directly with theire high-level counterparts.
- The low level functions are more flexible and therefor take more
- parameters. There are a lot of things that can only be done
- using the low-level words of the stream-interface. The most
- important words will be decribed here.
-
-
- NEXTBLOCK or LINKNEXT ( physblk -- next-physblk )
- Get the link to the next physical blocknumber within a
- blockstream. This is necessary when using systemvariables like
- BLK. In former times one could ind the preceeding block by 'BLK
- @ 1-'. These times are gone. Now it is 'BLK @ LASTBLOCK'. Note
- that the physical number is returned. Words like BLOCK, LOAD or
- BUFFER may not be applied to that number. The words (BLOCK,
- (LOAD and (BUFFER have to be used instead. The logical
- blocknumber during LOAD is hold in the USER-variable SBLK. The
- user should be very careful not to mix up BLK and SBLK.
-
-
- LASTBLOCK or LINKLAST ( physblk -- last-physblk )
- Same as NEXTBLOCK, but in the other direction. See notes there.
-
-
- SBLK ( -- addr )
- This is a USER-variable which contains the number of the logical
- block actually loaded. Use SBLK instead of BLK when working with
- blockstreams.
-
-
- BCREATE ( name length -- flag )
- Creates a blockstream with the given length. The name has to be
- a counted string. The returned flag is 0 when successful. The
- flag has value <>0 for different reasons, that cannot be seen
- from the flag. Errorconditions are a lack of diskspace or the
- stream to be created already exists.
-
-
- BDELETE ( name -- flag )
- Deletes a blockstream from the directory. The name has to be a
- counted string. The flag is 0 when successful. An errorcondition
- exists when the stream does not exist. The user has to take care
- that no stream-structure connected with the deleted stream will
- be used after deletion. (be VERY careful!)
-
-
- DCREATE ( name -- flag )
- Creates a subdirectory. The name has to be a counted string. The
- flag is 0 when successful. An errorcondition exists when there
- is not enough diskspace to create the directory, which needs at
- least one block.
-
-
- DDELETE ( name -- flag )
- Deletes a directory. The name has to be a counted string. The
- flag is 0 when successful. An errorcondition exists when the
- directory does not exist.
-
-
- CHANGEDIR ( name -- flag )
- Changes to the given directory. The name has to be a counted
- string. The flag is 0 when successful. Changing a directory
- means to put the physical number of the directory block into the
- USER- variable DIRECTORY. An errorcondition exists when the
- given directory does not exist.
-
-
-
- ###############################################################
- Lineeditor
- ###############################################################
-
- When porting F68K to a new system, the terminal control is
- sometimes very hardware/OS-dependent. So a full screen editor
- cannot work without changes, because this editor has to move the
- cursor,clear the screen, ... and so on. In order to be able to
- do this changes, there is a primitive lineeditor, which works on
- the 2k-blocks. All actions of this editor are invoked from the
- F68K commandline. They allow a rather fast and comfortable
- change in textlines. I have created this editor when F68K
- consisted of the kernel only. I had to CMOVE strings into the
- blocks. After doing this, the lineeditor is really comfortable.
-
-
- LIST ( nr -- )
- Displays the screen with the number given. The first column
- of the screen will contain the linenumbers with BASE 25. This
- number has to be used for all other actions with the editor. The
- blocknumber is saved in the variable SCR. For most terminals
- only have 80x25 characters, LIST will wait for a key to be
- pressed, otherwise the first line would always scroll away.
-
- L ( -- )
- Lists the block listed last again. It uses the number held
- in SCR.
-
- N ( -- )
- Lists the following block. This will be the block
- "SCR @ 1+".
-
- B ( -- )
- Lists the last block. This will be the block "SCR @ 1-".
-
- R ( -- ) \ R <nr>
- Shows the row <nr>. <nr> has to be given in BASE 25. So
- there is one digit only. The appropriate numbers are shown by
- LIST.
-
- C ( -- ) \ C <nr>
- Selects the column <nr> (decimal). This will be the actual
- writing position.
-
- $ ( -- ) \ $ <string>~
- Write the string <string> to the position selected by R and
- C. '~' is the delimiter of the string.
-
- Example:
- R h C 25 $ Hallo~
-
- will insert the string "Hallo" in row 17 and column 25.
-
-
- D ( -- )
- Deletes a character at the position selected with R and C.
-
- DM ( -- ) \ DM <nr>
- Delete Multiple; Deletes <nr> characters at the position
- given by R and C.
-
- DL ( -- ) \ DL <nr>
- Delete Line; Deletes the line <nr>. <nr> has to be given
- with BASE 25.
-
- IL ( -- ) \ IL <nr>
- Insert Line; Inserts a line at line <nr> (BASE 25).
-
- GL ( -- ) \ GL <nr>
- Get Line; Copies the given line <nr> (BASE 25) into special
- buffer.
-
- PL ( -- ) \ PL <nr>
- Put Line; Inserts the line from the buffer at the given
- linenumber (BASE 25).
-
-
- The user should be aware that this lineeditor is not simple, it
- is primitive. No error- or rangechecking is done. It is very
- easy to destroy the screen or to insert unEMITable characters.
- The user will not see them, but the compiler will. So the user
- has to be very carefull using the lineeditor.
-
-
-
- ###############################################################
- Fullscreen Editor
- ###############################################################
-
- F68K comes with a very simple full screen editor. Actually this
- editor was one the first programs I ever wrote in FORTH. It is
- capable to do the most necessary things only. In contrast to the
- lineeditor it is quite save and comfortable. No manual is
- necessary to use it. It is invoked using the command L ( nr -- )
- or V ( -- ), where V edits the screen most recently edited with
- L. A simple help can be read when typing ^?.
-
- The editor needs some cursor manipulation words. These should be
- preloaded. For details see the blockstream VT52-TERMINAL, where
- all desired words (and more) are defined.
-
- The cursor is moved around using the keys ^E, ^X, ^S and ^D. If
- keyboard in use has cursorkeys, then the keycodes in the table
- of actions in the editor's source can be changed easily. This
- table can be extended, too.
-
- I hope that one of the F68K users will write a better editor,
- which could support some functions of the streamsystem, in
- future.
-
-
-
- ###############################################################
- F-EDIT
- ###############################################################
-
- Markus Redeker has written a new fullscreen editor, which
- should be installed instead of the one described above. It is
- much more pleasant but uses some more facilities of a VT52
- terminal. It is possible to make the editor fit into different
- environments and different keycodes. So it is not longer
- necessary to use only the keycodes of a ASCII-keyboard.
- Cursorkeys or functionkeys may be used as well.
- Here is the original documentation written by Markus:
-
-
- The F-EDIT screen editor (Version 1.0)
-
-
- 1. How to get started (if F-EDIT is already installed)
-
- Start F-EDIT the usual way by typing <blk#> L to edit the block
- <blk#> of the USEd file. If this is the first block you edited,
- F-EDIT will ask for your ID. Enter your initials and the
- current date. They will be written automatically on the upper
- right corner of every block you have changed.
- The edited FORTH block fills the whole screen of the
- computer; messages and questions are displayed on the last
- line. To distinguish them from the edited text, they are
- displayed inverse.
- The use of the keys varies on different computers; to find
- out which key invokes which function, type the traditional HELP
- key of your computer (usually the key marked HELP, or that used
- as HELP key by most other programs) and you will see the help
- block with the ID you entered before on its upper right corner.
- Read it and type any key to resume to the edited FORTH block.
- Read also the following sections to understand the help screen
- better.
-
-
- 2. Some unusual features
-
- Current line:
- begins at cursor position (C) and ends 80 characters later:
-
- Cxxxxxxxxxxxx...
- ...xxxxxxxxxxxx
-
- This convention makes the line stack much more useful, but be
- aware of it if you want to delete a line.
-
-
- String input:
- F-EDIT displays the previous content of the edited string.
- Enter either the entire new string - or nothing if you don't
- want to change it. (Sorry, no input editing.)
-
-
- User's ID:
- After reading it, F-EDIT stores the identifier on the help
- screen and reads it again when the system is started the next
- time. So you can leave F68K, work in the operating system, and
- start F68K again without the need of entering always your name
- and the date. (This is specially useful after a crash...)
-
-
- 3. Words
-
- l ( blk# -- )
-
- edits the block of the USEd file with number <blk#>.
-
- v ( -- )
-
- calls the editor without initializing it: usually you can
- continue where you stopped editing before; when an error occurs
- while loading, the cursor is placed where the error occurred.
-
-
- 4. Structure of the program
-
- The program consists of two files: the file F-EDIT contains the
- main program and a "system file" contains system dependent
- definitions and the help block. It shall be named after the
- computer it is meant for: in my case it is called ATARI-EDIT.
-
-
- 5. Writing a System File
-
- 5.1. Loading the main program F-EDIT and call EDITOR vocabulary
-
- 5.2. Definition of the key table
-
- The key table consists of definitions of the form
-
- <key> --> <action>
-
- where <action> is one of the internal words of the editor that
- do the real work, and <key> is the number of the key that
- invokes that action. Which number you have to take depends on
- the definition of EDIT-KEY (see below). The possible <action>s
- can be found in ATARI-EDIT.
- Please use the key table of ATARI-EDIT as a model for
- your own key table to make a computer change easier. (The
- ATARI- EDIT key table is designed to be as compatible as
- possible to all FORTH screen editors I know.)
-
- 5.3. I/O words
-
- (The words REVERSE_VIDEO and NORMAL_VIDEO are expected to
- exist by F-EDIT.)
-
- The following words are DEFERred:
-
- EDIT-KEY ( -- key )
-
- is used instead of KEY by the editor to treat also the special
- keys (cursor keys, HELP key, ALT etc.) which are not ASCII.
- EDIT-KEY waits like KEY until a key is pressed and returns its
- number. The editor uses the result <key> only to compare it
- with the values in the key table; therefore you can code your
- keys how you like it (and have to do it, because there is no
- standard code). You can use all 32 bits of <key> - that is more
- than usually needed but was easier to program.
- Of course the editor needs also ASCII characters.
- Therefore EDIT-KEY stores the ASCII number of the key (if there
- is one) to the 8bit variable CHAR; it is taken from there if
- <key> is not found in the key table.
-
-
- SCREEN-I/O ( -- )
-
- prepares the screen for editing, by making it possible to
- write on the last position of the last line, and by other
- system-dependent actions.
-
-
- LINE-I/O ( -- )
-
- switches back to the normal i/o mode by undoing the actions of
- SCREEN-I/O. The editor calls LINE-I/O also before EXPECTing a
- string, which happens in inverse mode. So DO NOT switch from
- inverse to normal display!
-
- You have to take care of the cursor yourself, because there is
- no common way to handle it. Some programs show it only
- expecting an input, others always. On Atari, I prefer the first
- method because it is a bit faster.
-
-
- 5.4. Help block
-
- The help block is usually the last block of the System File.
- Store its absolute position in the variable HELPBLK by writing
-
- BLOCKSTREAM ALSO BLK @ NEXTBLOCK HELPBLK !
-
- in the last but one block. Defining a help block is absolutely
- necessary, because the editor uses the value of HELPBLK to
- check whether a system file has been loaded and refuses to
- start if HELPBLK = 0.
-
-
- 6. Bugs & other insects
-
- A system crash caused by F-EDIT seems unlikely (if F-EDIT is
- installed right), but there are some details that may cause
- problems:
-
- - F-EDIT refers to the help block by its absolute number. If
- you have changed the disk (which is possible at least with the
- ATARI loader), HELP would show you a block with less useful
- information.
- More problems arise when you also invoke the "Get ID"
- function: F-EDIT reads the ID from the help screen and writes
- it back afterwards. So, if you see some nonsense as previous
- ID, just press RETURN to let it how it was before.
-
- - The messages will be displayed in a better way as soon as
- F68K allows it.
-
-
-
- ###############################################################
- Possible errors
- ###############################################################
-
- This chapter shall prevent the users from possible errors, which
- are known to me. Some of them I made myself a couple of times.
- There is no order in these notes. I wrote them down like I found
- them.
-
-
- - If a blockstream has just been created using MAKE, it must be
- prepared for use with USE. USE is VERY likely to be forgotten. A
- common (errornous) sequence is
-
-
- MAKE test
- 10 MORE
-
-
- Now there is a blockstream 'TEST' with one block and an other
- blockstream has ten blocks more.
-
-
- - Headers can only be accessed when using `H'` instead of `'`.
-
-
-
-
- ###############################################################
- ###############################################################
- Documentation of loaders for different systems
- Implemtation specific notes
- ###############################################################
- ###############################################################
-
-
- ###############################################################
- Loader implementation for Atari ST
- ###############################################################
-
-
- The author of F68K (that's me) is the proud owner of an Atari
- ST. So the loader for this machine is the most sophisticated
- until now. First it was written in assembler and very simple,
- taking the blocks directly from Disk. To give away any sources
- meant to extract them from the disk and to put them into a DOS
- file.
-
- The next version has been written with the very nice freeware
- SOZOBON C-compiler. This allows easy expansion of the loader in
- the future. The F68K blockdevices are totally emulated within
- GEMDOS-files. A configuration file, which can be edited with any
- texteditor, is supported now to make installation easy. I will
- come to that later.
-
- The actual version was build using the commercial Turbo-C
- compiler, because there were to much bugs in the libraries of
- the SOZOBON system.
-
- The SOZOBON compiler seemed to be made to write F68K loaders.
- Only a very few lines of in-line assembler were enough to make
- the I/O functions fit the the F68K parameter protocol. But the
- source was not portable because the in-line assembler is very
- compiler dependent. Using the Turbo-C compiler the in-line code
- vanishes completely. But one has to use the compilerspecific
- keyword CDECL for all I/O functions to achieve that parameters
- are passed on the stack instead of passing them in registers.
-
- The configuration file contains the name of the system image,
- the sizes for code and data segments, the names of the READSYS
- inputfile and the WRITESYS outputfile (see 'Loader') as well as
- the number of devices and the names of the appropriate .SCR-
- files. Some errorchecking is done while interpreting this file,
- but the user should try to keep it clean, nevertheless. The
- order of the entries in this file may not be changed (it's C,
- not FORTH).
-
-
-
-
- Installation of F68K on Atari ST
-
- F68K for Atari ST will come completetly installed as a floppy
- based system. This is not very fast, especially using the
- blockstream system, but there is no reason not to install it on
- a hard- or ramdisk. Therefore a hard- or ramdisk must exist, of
- course. When putting the source to another device, a
- recompilation of F68K can be usefull, when the order or the size
- of the logical F68K devices, that means the GEMDOS files, have
- changed. Otherwise just a copy of one or all files to the
- desired place and changes to the corresponding entries in the
- F68K configuration file F68K.CFG have to be made. If the user
- wants to duplicate one file on a hard- or ramdisk, that means to
- hold the same file on floppydisk and on e.g. harddisk, he has to
- take care about the filesystem. It has to be UNMOUNTed before
- copying. After the copy completed and the necessary changes in
- the configuration file have been performed, both new F68K
- devices will have to MOUNTed again. That's all. VIEW will
- nevertheless search his information on the original device! To
- alter this, the user will have to recompile the system.
-
- Recompiling goes in two steps. It is possible to make the second
- one only. First the filesystem itself has to be loaded on top of
- the kernel. Therefore the name of the image in the configuration
- file has to be changed into KERNEL.IMG. The filesystem's sources
- are located in the file RAW.SCR, which indicates, that this
- device cannot be accessed via the blockstream system. If RAW.SCR
- is the first device in the configuration file, the system can be
- started and '1 LOAD' can be performed. If it is not, the user
- has to get the rootblock of the device from the ROOTTABLE and to
- store it in the USER-variable ROOTBLK, e.g. if it is the second
- (counted from 0) device
-
-
- 2 8* ROOTTABLE + 4+ @ ROOTBLK !
-
-
- Then again, '1 LOAD'.
-
-
- When loading finishes the new image can be saved using SAVE.
- This image now is a GEMDOS file with the name given in the
- configuration file behind 'output:'. This will be the new kernel
- in future.
-
- The user leaves F68K, changes the configuration file in order to
- use the new image and starts F68K again. It will use the
- blockstream system from now on.
-
- In the second step, the system extensions can be loaded. After
- changing to the appropriate device and saying 'MOUNT' for safety
- the user may change to the directory SYSTEM via
-
-
- CD SYSTEM
-
-
- There will be a blockstream called LOADME which can be loaded
- with
-
-
- USE LOADME
- 1 LOAD
-
-
- After the (hopefully) succesful completion, SAVE can be
- performed again (the user has to make sure that the former saved
- image is not overwritten now!).
-
- After that the system is installed completely and ready to use.
- VIEW will search on the logical devices where source has been
- compiled from.
-
-
-
-
-
- ###############################################################
- Loader implementation for Sinclair QL
- ###############################################################
-
-
-
- **************************************************
- *** ***
- *** Loader for ***
- *** ^^^^^^^^^^ ***
- *** F68K ***
- *** ^^^^ ***
- *** on the ***
- *** Sinclair QL ***
- *** ***
- *** by Dirk Kutscher ***
- *** ***
- **************************************************
-
- Content
- Hardware Requirements
- Files
- Getting started
- Special features
- Problems?
- Remark
-
-
- *************************
- * Hardware Requirements *
- *************************
-
- To start F68K on your QL you need at least one 3.5" disc drive
- and a minimum of 256 KB RAM. If you lack the disc drive you
- might be able to run F68K but should not try to use the
- Streaminterface to access DEVICE1_SCR since it is assumed to
- provide 300 blocks which you cannot emulate on microdrive. I am
- working at a mdv version at the moment.
-
-
- ************
- * FILES *
- ************
-
- The loader consists of the following files:
-
- bootF68K_QL
-
- This is a SuperBASIC-program which initialises the F68K-Disc for
- the use on a QL-System. If your F68K version was distributed on
- Atari Disc it is necessary to recreate the QLF68K_exe file (as
- well as QLCONFIG_exe) since the job information in the header of
- QL-files (Dataspace etc.) is not available on Atari Discs. Once
- you have run this program on your QL Disc you can happily forget
- it.
-
-
- QLF68K_EXE
-
- This the EXECutable loader created by boot. Start F68K by typing
- 'EXEC flp1_QLF68K_EXE'. Of course you can also use QRAM etc..
-
-
- QLF68K_CDE
-
- This is the machinecode program for loading F68K. If you have
- the -exe file installed it should not concern you anymore.
-
-
- QLF68K_ASM
-
- This is the assembler source for the loader. It will probably
- only assemble on Talent's Workbench Assembler, but it might give
- you some ideas of how to write your own loaders. (Of course you
- may also use it to expand the loader).
-
-
- QLF68K_TXT this one
-
-
- CHANGES_TXT loader development documentation
-
-
- QLCONFIG_exe
-
- This is the configuration utility for QLF68K_exe. It gives you
- the possiblity to patch the following filenames according to
- your personal hardware environment:
-
- flp1_F68K_img (the F68K bit image)
- flp1_F68K_out (the F68K output file)
- flp1_F68K_in (the F68K input file)
- flp1_DEVICE1_scr (Blockdevice for RW-access)
- flp1_STREAMS_scr ""
- ser1 (Printer device)
-
- If you like to keep these names you just have to confirm by
- hitting ENTER. You are then asked (in German), if you would like
- these names (except for the printer) to be questioned again when
- starting F68K. For experiments, first attempts etc. it might be
- useful to answer 'j' (for 'yes'). If you are familar with the
- system or even want save a complete application 'n' (for 'No')
- will make the loader start F68K directly when executed.
-
-
- QLCONFIG_cde
-
- The mc-file for the configuration utility. Loaded by
- bootF68K_QL.
-
-
-
- *******************
- * Getting started *
- *******************
-
- On executing QLF68K_exe the program first tries to allocate
- enough space in the memory for F68K. If the neccessary amount of
- bytes ($10000 + $20028 for code and data) is not available the
- execution will terminate.
-
- After this the program opens the console and gives you the
- possibility to change the names for the necessary files. (See
- files.QLConfig_exe) If you do change the names (e.g. the device)
- you should make sure that these files really exist and that they
- also can be accessed in the same way as the original file names.
- If no change is necessary just confirm by hitting ENTER.
-
- Now the program is loading the F68K-file (i.e 'flp1_F68K_IMG').
- If loading has been succesful F68K should now prompt with the
- copyright note and with it's 'ok'.
-
- If you want to access the Blockdevice now you should make sure
- that you can provide the specified files (e.g. DEVICE1_SCR and
- STREAMS_SCR) on the specified devices otherwise you might at
- least get an error report by QDOS or F68K. You do not have to
- worry about closing channels when changing discs (e.g. on a
- multitasking QL), since the RW routines are somewhat 'atomic' in
- this regard: They open and close their channels each time they
- are called. At first this seems to slow down the block accesses
- but thanks to QDOS this impression vanishes because all the
- often called directory blocks etc. are stored in slave blocks of
- the QDOS filing system.
-
-
-
- ********************
- * Special features *
- ********************
-
- Since F68K's editor uses VT52-sequences to control the cursor
- etc., which is normally non-standard on the QL, these control
- codes are emulated by the loader's I/O routines. There is also a
- translation table for some special characters ("Deutsche
- Umlaute") including ENTER, BACKSPACE etc.
-
- Nevertheless the user may still redirect I/O as he desires. I
- have provided three different EMIT routines each giving a
- different degree of emulation: Default is full emulation. The
- VT52-sequences as well as the the translation tables are
- supported. You could switch between these different modes by
- some simple FORTH words:
-
-
- : VT52_OFF ( -- ) EMITS 8 + @ ^EMIT ! ;
-
- : VT52_ON ( -- ) EMITS 4 + @ ^EMIT ! ;
-
- : NO_TRANSLATION ( -- ) EMITS 12 + @ ^EMIT ! ;
-
-
-
-
- *************
- * Problems? *
- *************
-
- Problems may occur if you have got the TOS-formatted F68K disc
- and are not able to create the appropriate QL disc, probably
- because you lack a disc driver or a transformation utility. In
- such a case you can send me (adress below) two QDOS-formatted
- 3.5" discs AND a paid and self-adressed envelope and I will rush
- you the latest QL version as soon as possible.
-
-
-
- **********
- * Remark *
- **********
-
- I have written this loader to support both the spread of the
- programming language Forth and QDOS, the operating system of the
- QL. So you can make as many copies of the loader as you want and
- also distribute them as long as no profit is gained by the
- distribution. I would also like my name to be kept visible
- etc...
-
- The programme has been successfully tested on R. Kowallik's
- QL-Emulator for the Amiga.
-
- I have no objections to somebody writing a C version of the
- loader nor other improvements. I would be pleased to hear from
- you then!
-
- For suggestions, questions or any other comments please use the
- following adress:
-
- Dirk Kutscher
- Kastanienweg 39
- 2804 Lilienthal
- Germany
-
- You can also contact me via eMail using one of the following
- adresses:
-
- Dirk_Kutscher@HB.MAUS.DE
-
- Karl @ BBS.FORTH-eV.de
-
-
-
- ###############################################################
- Loader implementation for Commodore Amiga
- ###############################################################
-
- The amiga support for the F68K consists of 4 files:
-
- --- LOAD4TH the loader
- --- LOAD4TH.c it's source
- --- LOAD4TH.info the logo to start it from the workbench
- --- and this file.
-
- In general, it's in functional agreement with the atari Loader
- for the F68K, especially concerning the environment handling
- with the configuration file F68K.CFG.
-
- I added two little options to get screen data printed on paper:
-
- --- Starting "LOAD4TH p" opens the file "dump.dat" in the
- current directory and puts all bytes into it, that passed
- through the "Emit" function.
-
- --- starting "LOAD4TH s" does the same with the exception, that
- CR's are are filtered out, furthermore any byte that follows a
- LF. This provides a very simple and effective method to print
- screens. (I like programming in bed, and because the amiga isn't
- a laptop..) It is applied to the F68K "list" word, and very
- little extra work on a conventional editor is necessary to clean
- out the rest of OS-garbage contained in the file.
-
- Since the amiga uses some special keycodes, three commands of
- the fullscreen-editor had to be changed:
-
- ^F instead of ^? calls the help screen
- ^V instead of ^< does #1.load
- ^\ instead of ^> does load.exit
-
- Despite of this, all operation is the same as described in the
- F68K original documentation. Before first use, the blockfiles
- have to be "unmount"ed and "mount"ed again as described in the
- technical manual.
-
- To start F68K from the workbench, the ".info"-file has to be
- copied into the same directory, where the loader is. It will put
- the appropriate logo on the workbench. The p and s option are
- available from the CLI only.
- If you have received these files not on an amiga-formatted
- disk, the file "LOAD4TH.info" might have been renamed as
- "LOAD4TH.inf" to be in line with naming rules. When transferring
- this file to the amiga, it must be renamed to "LOAD4TH.info",
- otherwise your workbench will not show it.
-
- There is (at the present state of development) one major
- problem, which should not be disregarded:
-
- This loader opens a RAW: window on the amiga, which is quite
- easy to program, but has a fixed line resolution of 77 true
- characters per row. (There is a horizontal resolution of 80
- Characters of this standard font, but two are lost for the
- borderlines and one is reserved to place the leading cursor). If
- anybody knows a simple trick to smash this on DOS-level, let me
- hear.
-
- Questions and hints:
-
- Wolfgang Schemmert
- Luisenstr. 51
- W-6050 Offenbach
- Tel. 069-88 56 06
- FAX 069-81 10 50
-
-
-
-
-
- ###############################################################
- Glossary
- ###############################################################
-
-
- (ABS) ( absaddr -- reladdr )
-
- Vocabulary FORTH
-
- Converts an absolute address into a standard F68K-datapointer.
-
- Example:
- 0 (ABS) @
- \ gives the boot SSP
-
-
-
-
- (ABSCODE) ( absaddr -- code-reladdr )
-
- Vocabulary FORTH
-
- Converts an absolute address into a standard F68K-datapointer.
-
- Example:
- 0 (ABSCODE) CODE>DATA @
- \ gives the boot-SSP.
-
-
-
-
- (EMIT) ( -- addr )
-
- Vocabulary FORTH
-
- (EMIT) is a USER-Variable, which contains an F68K pointer to
- the word, which is executed by EMIT. It is preset with
- LOADEREMIT.
-
-
-
-
-
- (EXPECT) ( -- adr )
-
- Vocabulary FORTH
-
- (EXPECT) is a USER-variable which contains the CFA of the word
- which will be used by EXEPCT.
-
-
-
-
-
- (FIND ( string -- controlword cfa | string -1 )
-
- Vocabulary FORTH
-
- Searches for a word with the name given with the string in the
- vocabularies found in the search order. (FIND uses VOCSEARCH.
-
- Example:
- " DUP" (find
- \ or
- ' (find Is find
- " DUP" find
-
-
-
-
- (KEY) ( -- addr )
-
- Vocabulary FORTH
-
- (KEY) is a USER-Variable, which contains an F68K pointer to the
- word, which is executed by KEY. It is preset with LOADERKEY.
-
-
-
-
-
- (KEY?) ( -- addr )
-
- Vocabulary FORTH
-
- (KEY?) is a USER-Variable, which contains an F68K pointer to
- the word, which is executed by KEY?. It is preset with
- LOADERKEY?.
-
-
-
-
-
- (R/W) ( -- addr )
-
- Vocabulary FORTH
-
- (R/W) is a USER-Variable, which contains an F68K pointer to the
- word, which is executed by R/W. It is preset with LOADERR/W.
-
-
-
-
-
- (READSYS) ( -- addr )
-
- Vocabulary FORTH
-
- (READSYS) is a USER-Variable, which contains an F68K pointer to
- the word, which is executed by READSYS. It is preset with
- LOADERREADSYS.
-
-
-
-
-
- (TYPE) ( -- adr )
-
- Vocabulary FORTH
-
- (TYPE) is a USER-variable which contains the CFA of the word
- which will be used by TYPE.
-
-
-
-
-
- (WRITESYS) ( -- addr )
-
- Vocabulary FORTH
-
- (WRITESYS) is a USER-Variable, which contains an F68K pointer
- to the word, which is executed by WRITESYS. It is preset with
- LOADERWRITESYS.
-
-
-
-
-
- .LAST ( -- )
-
- Vocabulary FORTH
-
- Prints the name of the most recently defined word.
-
-
-
-
-
- >ABS ( reladdr -- absaddr )
-
- Vocabulary FORTH
-
- Converts a standard F68K-datapointer into an absolute address.
-
- Example:
- 0 >ABS
- \ gives the physical start of datasegement
-
-
-
-
- >ABSCODE ( code-reladdr -- absaddr )
-
- Vocabulary FORTH
-
- Converts a standard F68K-codepointer into an absolute address.
-
- Example:
- 0 >ABSCODE
- \ gives the physical start of codesegement
-
-
-
-
- >R ( n -- )
-
- Vocabulary FORTH
-
- Pushes the top of stack onto the returnstack. A conversion is
- done so that a standard F68K-codepointer becomes an absolute
- machineaddress on the returnstack. 'R>' and 'R@' reconvert the
- value on the returnstack so that conversion should be invisible
- to the user.
-
-
-
-
-
- ?CR ( column -- )
-
- Vocabulary FORTH
-
- If the actual writing column (held in OUT) is greater than the
- given column, a CR is performed.
-
-
-
-
-
- [VOC'] ( -- ) \ : ... [voc'] <vocname> ... ;
-
- Vocabulary FORTH
-
- Finds the address of the named vocabulary. This may be very
- usefull together with searching word VOCSEARCH. The returned
- address corresponds to those held in CURRENT or CONTEXT. This
- is the compiletime version of VOC'.
-
- Example:
- : findDUP
- " DUP" [voc'] forth vocsearch ;
- \ see also VOC'
-
-
-
-
- ^EMIT ( -- addr )
-
- Vocabulary FORTH
-
- ^EMIT is a vector which contains the function which is actually
- used to emit a character. Normally, I would have named such a
- vector (EMIT), but in this case the content of ^ EMIT is not
- executable by EXECUTE, for it needs somw interfacing provided
- by EMIT, which calls the function ^EMIT points to.
-
-
-
-
-
- ^KEY ( -- addr )
-
- Vocabulary FORTH
-
- ^KEY is a vector which contains the function which is actually
- used to get a character from the terminal (or from elsewhere).
- See ^EMIT!
-
-
-
-
-
- ^KEY? ( -- addr )
-
- Vocabulary FORTH
-
- ^KEY? is a vector which contains the function which is actually
- used to check the state of the terminal. See ^EMIT!
-
-
-
-
-
- ^R/W ( -- addr )
-
- Vocabulary FORTH
-
- ^R/W is a vector which contains the function which is actually
- used to read or write from/to mass storage. See ^EMIT!
-
-
-
-
-
- ^READSYS ( -- addr )
-
- Vocabulary FORTH
-
- ^READSYS is a vector which contains the function which is
- actually used to read a file in a system dependent manner. See
- ^EMIT!
-
-
-
-
-
- ^WRITESYS ( -- addr )
-
- Vocabulary FORTH
-
- ^WRITESYS is a vector which contains the function which is
- actually used to write a file in a system dependent manner. See
- ^EMIT!
-
-
-
-
-
- ALSO ( -- )
-
- Vocabulary ONLY
-
- ALSO is a 'DUP' on vocabulary-stack. The first vocabulary in
- the search order is searched twice after ALSO. In most cases,
- this first vocabulary will be replaced by an other one.
-
- Example:
- FLOAT ALSO FORTH
- \ The use of 'ALSO' is reverse to 'TOSS'.
-
-
-
-
- BACKSPACE ( -- )
-
- Vocabulary FORTH
-
- Emits the ASCII-Code 8 in order to move the cursor one column
- to left.
-
- Example:
- : backspace ( -- ) 8 emit ;
-
-
-
-
- BACKSPACES ( n -- )
-
- Vocabulary FORTH
-
- Executes BACKSPACE in a loop.
-
-
-
-
-
- BCREATE ( name length -- flag )
-
- Vocabulary BLOCKSTREAM
-
- Creates a blockstream with the given length. The name has to be
- a counted string. The returned flag is 0 when successful. The
- flag has value <>0 for different reasons, that cannot be seen
- from the flag. Errorconditions are a lack of diskspace or the
- stream to be created already exists.
-
-
-
-
-
- BDELETE ( name -- flag )
-
- Vocabulary BLOCKSTREAM
-
- Deletes a blockstream from the directory. The name has to be a
- counted string. The flag is 0 when successful. An
- errorcondition exists when the stream does not exist. The user
- has to take care that no stream-structure connected with the
- deleted stream will be used after deletion. (be VERY careful!)
-
-
-
-
-
- BELL ( -- )
-
- Vocabulary FORTH
-
- Writes '7' to the terminal which should respond with noise.
-
- Example:
- : bell ( -- ) 7 emit ;
-
-
-
-
- BLK ( -- addr )
-
- Vocabulary FORTH
-
- BLK is a USER-variable, which contains the number of the
- physical block actually loaded.
-
-
-
-
-
- BYE ( ?? -- )
-
- Vocabulary FORTH
-
- Leaves the F68K interpreter and gives control back to the
- loader.
-
-
-
-
-
- CAPACITY ( -- n )
-
- Vocabulary FORTH
-
- Gives the length of the current blockstream.
-
- Example:
- 1 capacity index
- \ INDEX for the whole blockstream
-
-
-
-
- CAPS ( -- addr )
-
- Vocabulary FORTH
-
- This USER-variable decides wether strings isolated from the
- inputstream are capitalized. This can be very useful when
- 'misusing' the interpreter.
-
-
-
-
-
- CD ( -- ) \ CD <name> or CD
-
- Vocabulary FORTH
-
- This will change to the directory given in <name>. If no <name>
- is given, then the actual directory path is printed on the
- terminal.
-
-
-
-
-
- CELL+ ( n -- n+4 )
-
- Vocabulary FORTH
-
- Increases n by the width of one addresscell = 4 bytes.
-
-
-
-
-
- CELL- ( n -- n-4 )
-
- Vocabulary FORTH
-
- Decreases n by the width of one addresscell = 4 bytes.
-
-
-
-
-
- CELLS ( n -- n*4 )
-
- Vocabulary FORTH
-
- Calculates the width of n addresscells.
-
- Example:
- CREATE FIELD
- 0 , 1 , 2 , 3 , 4 , 5 ,
- : 3 ( -- 3 )
- FIELD 3 CELLS + @ ;
-
-
-
-
- CHANGEDIR ( name -- flag )
-
- Vocabulary BLOCKSTREAM
-
- Changes to the given directory. The name has to be a counted
- string. The flag is 0 when successful. Changing a directory
- means to put the physical number of the directory block into
- the USER- variable DIRECTORY. An errorcondition exists when the
- given directory does not exist.
-
-
-
-
-
- CHAR+ ( addr -- addr+1 )
-
- Vocabulary FORTH
-
- Calculates the address of the following character.
-
-
-
-
-
- CHARS ( n -- n )
-
- Vocabulary FORTH
-
- Calculates the address distance of <n> characters. In F68K,
- CHARS is a dummy, because the length of a character is 1.
-
-
-
-
-
- CODE! ( n coderelative-addr -- )
-
- Vocabulary FORTH
-
- Stores a value into the codesegment. See CODE@ and CODE>DATA.
-
- Example:
- : CODE! CODE>DATA ! ;
-
-
-
-
- CODE>DATA ( coderelative-addr -- datarelative-addr )
-
- Vocabulary FORTH
-
- Converts an address, which is relative to the codesegment, into
- an address relative to the datasegment.
-
-
-
-
-
- CODE@ ( coderelative-addr -- n )
-
- Vocabulary FORTH
-
- Fetches a value from the codesegment, e.g. '-addresses. See
- CODE! and CODE>DATA.
-
- Example:
- : CODE@ CODE>DATA @ ;
- ' PARSER CELL+ CODE@ @
- \ get the pointer to the runtime routine
- \ of the DEFERed PARSER
- \ = ' INTERPRETER or ' COMPILER
-
-
-
-
- COLUMNS ( -- addr )
-
- Vocabulary FORTH
-
- Variable which holds the number of available columns on the
- current terminal.
-
-
-
-
-
- COMPILER ( addr -- )
-
- Vocabulary FORTH
-
- COMPILER tries to compile the input stream. It is used by
- INTERPRET when STATE <>0.
-
-
-
-
-
- DCREATE ( name -- flag )
-
- Vocabulary BLOCKSTREAM
-
- Creates a subdirectory. The name has to be a counted string.
- The flag is 0 when successful. An errorcondition exists when
- there is not enough diskspace to create the directory, which
- needs at least one block.
-
-
-
-
-
- DDELETE ( name -- flag )
-
- Vocabulary BLOCKSTREAM
-
- Deletes a directory. The name has to be a counted string. The
- flag is 0 when successful. An errorcondition exists when the
- directory does not exist.
-
-
-
-
-
- DEL ( -- ) \ DEL <name>
-
- Vocabulary FORTH
-
- This will delete the blockstream with the given name. If the
- stream has former been USEd, the F68K word created there will
- not be deleted!
-
-
-
-
-
- DELDIR ( -- ) \ DELDIR <name>
-
- Vocabulary FORTH
-
- This will delete a directory. Notice that this directory has to
- be empty, e.g. it may contain nor streams neither directories,
- otherwise an error condition exists.
-
-
-
-
-
- DIR ( -- )
-
- Vocabulary FORTH
-
- Shows the content of the current directory.
-
-
-
-
-
- DIRECT ( -- )
-
- Vocabulary FORTH
-
- Switches the blockstreamsystem of. Now BLOCK, LOAD and BUFFER
- access the physical blocks again. The variable ROOTBLK is
- deleted.
-
-
-
-
-
- DROP ( n -- )
-
- Vocabulary FORTH
-
- DROPs the top element on stack (TOS).
-
-
-
-
-
- DUP ( n -- n n )
-
- Vocabulary FORTH
-
- DUPlicates the top of stack (TOS).
-
-
-
-
-
- EMIT ( character -- )
-
- Vocabulary FORTH
-
- Writes the character on the stack to the terminal. EMIT uses
- the function stored in the USER-variable ^EMIT. This function
- must use one of the loaders I/O-routines, which are stored in
- the array EMITS, because some interfacing has to be done with
- these routines.
-
-
-
-
-
- EMITS ( -- addr )
-
- Vocabulary FORTH
-
- Gives the address of an array, which holds the number and the
- entry-addresses of the loaders I/O-functions to emit a
- character to the terminal. 'EMITS @' gives the number of the
- functions. 'EMITS 4+ @' is the address of the first routine.
- The routines in this table may not be executed from F68K
- because they need some interfacing provided by EMIT.
-
-
-
-
-
- EVALUATE ( c-addr count -- )
-
- Vocabulary FORTH
-
- This is an explicite call of the outer interpreter. The string
- at c-addr with the length count is interpreted. EVALUATE may be
- nested.
-
- Example:
- " 1 2 3 . . . " EVALUATE
- \ gives: 3 2 1
-
-
-
-
- EXPEL ( where amount -- )
-
- Vocabulary BLOCKSTREAM
-
- This will cut <amount> blocks out of the current blockstream.
- The block <where> will not be cut, it remains in the stream. To
- remember this, remember that the first block of a stream cannot
- be EXPELled.
-
- Example:
- 3 2 EXPEL
- \ will cut the block 4 and 5
- \ from the stream
-
-
-
-
- FIND ( string -- controlword cfa | string -1 )
-
- Vocabulary FORTH
-
- Searches for a word with the name given with the string in the
- vocabularies found in the search order. FIND is a deferred word
- and initially executes (FIND.
-
- Example:
- " DUP" find
- \ using kernel's FIND:
- ' (find Is find
-
-
-
-
- FORTHPARAS ( -- addr )
-
- Vocabulary FORTH
-
- Gives a pointer to a structure which is provided by the loader
- and holds all parameters the loader passes to F68K. F68K itself
- will store the loaders registers here in order to give the
- loader access to its own runtime environment. The FORTHPARAS
- are of following structure:
-
- Example:
- struct forthparas
- {
- long registers[16];
- /* to be filled by F68K */
- void *data, *code;
- void *datstk; *retstk;
- void *TIBptr;
- void *keytable;
- void *keyqtable;
- void *r_wtable;
- void *readsystable;
- void *writesystable;
- void *roottable;
- }forthparas;
-
-
-
-
- INCLUDE ( -- ) \ INCLUDE <filename>
-
- Vocabulary FORTH
-
- This is an interactive word to 'USE 1 LOAD' a blockstream. This
- is usefull, because it is not allowed to 'USE 1 LOAD' streams
- from within other USEd streams. USEing a stream while loading
- another USEd streams implies to make the new stream the actual
- one. So there is no return! INCLUDE saves the actual stream and
- restores it again (see SAVE_STREAM, RESTORE_STREAM).
-
-
-
-
-
- INDEX ( fromblock toblock -- )
-
- Vocabulary FORTH
-
- Gives a list of the first lines in the specified range of
- blocks. There is a convention that the first line in each
- screen has to be a comment.
-
- Example:
- 1 capacity index
- \ INDEX for the whole blockstream
-
-
-
-
- INSERT ( where amount -- )
-
- Vocabulary FORTH
-
- This will insert <amount> blocks at the position <where> in the
- blockstream.
-
-
-
-
-
- INTERPRET ( -- )
-
- Vocabulary FORTH
-
- This is the outer interpreter of the F68K-system. It will
- expect some source code provided by SOURCE and interpret it
- (surprising, isn't it?). It will return when the input stream
- is exhausted, e.g. WORD gives back a NULLSTR?. INTERPRET
- executes the DEFERed word PARSER to handle a string from the
- source. PARSER holds either COMPILER or INTERPRETER.
-
- Example:
- : INTERPRET ( -- )
- BEGIN
- NAME NULLSTR?
- WHILE
- PARSER
- AGAIN ;
-
-
-
-
- INTERPRETER ( addr -- )
-
- Vocabulary FORTH
-
- INTERPRETER tries to interpret the input stream provided by
- SOURCE. It is used by INTERPRET when STATE=0.
-
-
-
-
-
- KEY ( -- character )
-
- Vocabulary FORTH
-
- Reads a character from the terminal. KEY uses the function
- stored in the USER-variable ^KEY. This function must use one of
- the loaders I/O-routines, which are stored in the array KEYS,
- because some interfacing has to be done with these routines.
-
-
-
-
-
- KEY? ( -- flag )
-
- Vocabulary FORTH
-
- Checks the terminal for availability of a character. KEY? uses
- the function stored in the USER-variable ^KEY?. This function
- must use one of the loaders I/O-routines, which are stored in
- the array KEY?S, because some interfacing has to be done with
- these routines.
-
-
-
-
-
- KEY?S ( -- addr )
-
- Vocabulary FORTH
-
- Gives the address of an array, which holds the number and the
- entry-addresses of the loaders I/O-functions to check the state
- of the terminal. 'KEY?S @' gives the number of the functions.
- 'KEY?S 4+ @' is the address of the first routine. The routines
- in this table may not be executed from F68K because they need
- some interfacing provided by KEY?.
-
-
-
-
-
- KEYS ( -- addr )
-
- Vocabulary FORTH
-
- Gives the address of an array, which holds the number and the
- entry-addresses of the loaders I/O-functions to read a
- character from the terminal. 'KEYS @' gives the number of the
- functions. 'KEYS 4+ @' is the address of the first routine. The
- routines in this table may not be executed from F68K because
- they need some interfacing provided by KEY.
-
-
-
-
-
- LASTBLK ( -- addr )
-
- Vocabulary FORTH
-
- This is a global variable, which holds the number of the
- physical block last recently referred. Internally it is used to
- access the actual blockbuffer very fast during LOAD together
- with the content of LASTBUF. It may be very helpful while
- debugging the blockstream system!
-
-
-
-
-
- LASTBLOCK or LINKLAST ( physblk -- last-physblk )
-
- Vocabulary BLOCKSTREAM
-
- Same as NEXTBLOCK, but in the other direction. See notes there.
-
-
-
-
-
- LASTBUF ( -- addr )
-
- Vocabulary FORTH
-
- This is a global variable, which holds the address of the
- blockbuffer last recently used by BLOCK. Internally it is used
- to access the actual blockbuffer very fast during LOAD together
- with the content of LASTBLK. It may be very helpful while
- debugging the blockstream system!
-
-
-
-
-
- LESS ( n -- )
-
- Vocabulary FORTH
-
- This will reduce the blockstream currently in USE by n blocks.
- They will be taken from the end of the stream.
-
-
-
-
-
- LINKLAST ( block -- lastblock )
-
- Vocabulary BLOCKSTREAM
-
- Synonym for LASTBLOCK.
-
-
-
-
-
- LINKNEXT ( block -- nextblock )
-
- Vocabulary BLOCKSTREAM
-
- Synonym for NEXTBLOCK.
-
-
-
-
-
- LOAD ( blocknumber -- )
-
- Vocabulary FORTH
-
- Loads the block with the given number. During load, this number
- is contained in the USER-variable BLK. BLK always contains the
- physical blocknumber loaded!!
-
-
-
-
-
- LOADEREMIT ( char -- )
-
- Vocabulary FORTH
-
- Executes the content of the USER-vector ^EMIT. Parameters are
- converted from F68K to a standard C-format. So the content of
- must not be executed using EXECUTE, but only by using
- LOADEREMIT. ^EMIT can take one of the addresses held in the
- array EMITS.
-
-
-
-
-
- LOADERKEY ( -- char )
-
- Vocabulary FORTH
-
- Executes the content of the USER-vector ^KEY. Parameters are
- converted from F68K to a standard C-format. So the content of
- must not be executed using EXECUTE, but only by using
- LOADERKEY. ^KEY can take one of the addresses held in the array
- KEYS.
-
-
-
-
-
- LOADERKEY? ( -- flag )
-
- Vocabulary FORTH
-
- Executes the content of the USER-vector ^KEY?. Parameters are
- converted from F68K to a standard C-format. So the content of
- must not be executed using EXECUTE, but only by using
- LOADERKEY?. ^KEY? can take one of the addresses held in the
- array KEYS?.
-
-
-
-
-
- LOADERR/W ( buffer blocknumber r/w-flag -- )
-
- Vocabulary FORTH
-
- Executes the content of the USER-vector ^R/W. Parameters are
- converted from F68K to a standard C-format. So the content of
- must not be executed using EXECUTE, but only by using
- LOADERR/W. ^R/W can take one of the addresses held in the array
- R/WS.
-
-
-
-
-
- LOADERREADSYS ( addr count -- flag )
-
- Vocabulary FORTH
-
- Executes the content of the USER-vector ^READSYS. Parameters
- are converted from F68K to a standard C-format. So the content
- of must not be executed using EXECUTE, but only by using
- LOADERREADSYS. ^READSYS can take one of the addresses held in
- the array READSYSES.
-
-
-
-
-
- LOADERWRITESYS ( addr count -- flag )
-
- Vocabulary FORTH
-
- Executes the content of the USER-vector ^WRITESYS. Parameters
- are converted from F68K to a standard C-format. So the content
- of must not be executed using EXECUTE, but only by using
- LOADERWRITESYS. ^WRITESYS can take one of the addresses held in
- the array WRITESYSES.
-
-
-
-
-
- LOCAL ( n -- ) \ <n> LOCAL <name>
-
- Vocabulary FORTH
-
- Creates a datatype similar to 'VALUE', but only within a
- colon-definition. The memory for the data is allocated on the
- returnstack.
-
-
-
-
-
- MAKE ( -- ) \ MAKE <name>
-
- Vocabulary FORTH
-
- This will create a blockstream with length 1 in store it into
- the actual directory or in the directory given together with
- <name>.
-
-
-
-
-
- MAKEDIR ( -- ) \ MAKEDIR <name>
-
- Vocabulary FORTH
-
- This will create a subdirectory with the given name.
-
-
-
-
-
- MORE ( n -- )
-
- Vocabulary FORTH
-
- This will extend the blockstream which is currently in USE by n
- further blocks. They will be appended to the end of the stream.
-
-
-
-
-
- MOUNT ( -- )
-
- Vocabulary FORTH
-
- This will initialise a blockstream system copied to a device.
- For directories contain physical blocknumbers, they are not
- portable to other devices, where other blocknumbers are used.
- MOUNT makes the blockstream system fit to the actual device.
- Note that only a system, that has been UNMOUNTed, can be
- mounted. Always make sure that you are working with MOUNTed
- systems only. Oterhwise malfunction is guaranteed. It is not
- possible to doubly MOUNT a system.
-
-
-
-
-
- NEXTBLOCK or LINKNEXT ( physblk -- next-physblk )
-
- Vocabulary BLOCKSTREAM
-
- Get the link to the next physical blocknumber within a
- blockstream. This is necessary when using systemvariables like
- BLK. In former times one could ind the preceeding block by 'BLK
- @ 1-'. These times are gone. Now it is 'BLK @LASTBLOCK'. Note
- that the physical number is returned. Words like BLOCK, LOAD or
- BUFFER may not be applied to that number. The words (BLOCK,
- (LOAD and (BUFFER have to be used instead. The logical
- blocknumber during LOAD is held in the USER-variable SBLK. The
- user should be very careful not to mix up BLK and SBLK.
-
-
-
-
-
- NIP ( a b -- b )
-
- Vocabulary FORTH
-
- Discards the second element on stack (SOS).
-
-
-
-
-
- ORDER ( -- )
-
- Vocabulary FORTH
-
- Prints the actual search order.
-
-
-
-
-
- OUT ( -- addr )
-
- Vocabulary FORTH
-
- USER-variable, which counts EMITs. It is reset by CR. OUT is
- used to realize TABs or conditional CRs.
-
-
-
-
-
- OVER ( a b -- a b a )
-
- Vocabulary FORTH
-
- Copies the second element on stack (SOS) to the top.
-
-
-
-
-
- PUSH ( addr -- )
-
- Vocabulary FORTH
-
- Saves the content of addr on the returnstack. It will be
- restored with the next 'EXIT' or ';' statement.
-
- Example:
- : hex.
- base push
- $10 base !
- . ;
-
-
-
-
- QUIT ( ?? -- ?? )
-
- Vocabulary FORTH
-
- Invokes the outer F68K interpreter (for F68K is a native code
- system, there is no inner interpreter at all). The returnstack
- is reset and the datastack is tested for underflow.
-
-
-
-
-
- R/W ( buffer blocknumber rwflag -- )
-
- Vocabulary FORTH
-
- Writes or reads 2048 bytes from/to the buffer from/to the block
- with the given number on the mass storage device. R/W uses the
- function stored in the USER-variable (R/W). This function
- normally should use one of the loaders I/O-routines, which are
- stored in the array R/WS. rwflag=0: read; rwflag<>0:write;
-
-
-
-
-
- R/WS ( -- addr )
-
- Vocabulary FORTH
-
- Gives the address of an array, which holds the number and the
- entry-addresses of the loaders I/O-functions to read/write a
- block from/to the mass storage device. to the terminal. 'R/WS @
- ' gives the number of the functions. 'R/WS 4+ @' is the address
- of the first routine. The routines in this table may not be
- executed from F68K because they need some interfacing provided
- by R/W.
-
-
-
-
-
- R> ( -- n )
-
- Vocabulary FORTH
-
- Pops a value from the returnstack onto the normal datastack.
- This value should have been pushed onto the returnstack using
- '>R', because addressconversion and -reconversion is done in a
- '>R'-'R>' pair. See '>R'.
-
-
-
-
-
- R@ ( -- n )
-
- Vocabulary FORTH
-
- Copies a value from the returnstack onto the normal datastack.
- This value should have been pushed onto the returnstack using
- '>R', because addressconversion and -reconversion is done in a
- '>R'-'R@' pair. See '>R'.
-
-
-
-
-
- READSYS ( addr count -- flag )
-
- Vocabulary FORTH
-
- Reads 'count' bytes to the buffer 'addr' in a systemdependent
- manner. READSYS calls a routine supplied by the loader.
-
-
-
-
-
- READSYSES ( -- addr )
-
- Vocabulary FORTH
-
- Gives the address of an array, which holds the number and the
- entry-addresses of the loaders I/O-functions to read from a
- file in a system dependent manner. 'READSYSES @' gives the
- number of the functions. 'READSYSES 4+ @' is the address of the
- first routine. The routines in this table may not be executed
- from F68K because they need some interfacing provided by
- READSYS.
-
-
-
-
-
- RESTORE_STREAM ( -- )
-
- Vocabulary FORTH
-
- Restores the actual streamcontext from the returnstack. So it
- can only be used in conjunction with SAVE_STREAM on one
- executionlevel (because of the returnstackmanipulation).
-
-
-
-
-
- ROWS ( -- addr )
-
- Vocabulary FORTH
-
- Variable which holds the number of available rows on the
- current terminal.
-
-
-
-
-
- RP! ( returnstackpointer -- )
-
- Vocabulary FORTH
-
- Set a new returnstack. Possibly can be used in conjunction with
- RP@. Handle with care!
-
-
-
-
-
- RP@ ( -- returnstackpointer )
-
- Vocabulary FORTH
-
- Gets the actual pointer to the bottom of the returnstack. Note
- that 'R@' cannot be replaced by 'RP@ @' because
- addressconversion is done within 'R@'. It can be replaced by
- 'RP@ @ (ABSCODE)' doing the reconverion 'by hand'.
-
-
-
-
-
- SAVE-SYSTEM ( -- )
-
- Vocabulary FORTH
-
- Uses the WRITESYS-function to create a new image of F68K, which
- can be reloaded by the system-dependend loader.
-
-
-
-
-
- SAVE_STREAM ( -- )
-
- Vocabulary FORTH
-
- Saves the actual streamcontext on the returnstack. This context
- may be changes afterwards but has to be restored by
- RESTORE_CONTEXT on the same executionlevel (because of the
- returnstackmanipulation).
-
-
-
-
-
- SAVEAREA ( addr count -- )
-
- Vocabulary FORTH
-
- Same as PUSH, but for an area of memory. count bytes from addr
- will be saved on the returnstack and be restored with the next
- 'EXIT' or ';' statement. It is used within 'EVALUATE' in order
- to save the content of TIB.
-
-
-
-
-
- SBLK ( -- addr )
-
- Vocabulary BLOCKSTREAM
-
- This is a USER-variable which contains the number of the
- logical block actually loaded. Use SBLK instead of BLK when
- working with blockstreams.
-
-
-
-
-
- SPACE ( -- )
-
- Vocabulary FORTH
-
- Emits the constant BL =$20 to the terminal.
-
- Example:
- : space ( -- ) bl emit ;
-
-
-
-
- SPACES ( n -- )
-
- Vocabulary FORTH
-
- Executes SPACE in a loop.
-
-
-
-
-
- STREAM: ( -- ) \ STREAM: <name>
-
- Vocabulary BLOCKSTREAM
-
- Defining word for streamstructures. One example is USESTREAM
- used by USE.
-
- Example:
- STREAM:XX
- XX " TEST" ?BUSE
-
-
-
-
- STREAMS ( -- )
-
- Vocabulary FORTH
-
- Invokes the blockstreamsystem. Now BLOCK, LOAD and BUFFER
- access the logical blocks within the system. The variable
- ROOTBLK is cleared and must to be changed!
-
-
-
-
-
- TAB ( n -- )
-
- Vocabulary FORTH
-
- Moves the cursor to column n in the actual line. TAB uses OUT
- to count the cursors position.
-
-
-
-
-
- TOSS ( -- )
-
- Vocabulary ONLY
-
- 'TOSS' is a 'DROP' for the vocabulary-stack. It will often be
- used in conjunction with 'ALSO', which increases the
- vocabulary-stack.
-
-
-
-
-
- UNLOOP ( -- )
-
- Vocabulary FORTH
-
- UNLOOP is used when it is necessary to EXIT a word from within
- a DO-LOOP-structure.
-
- Example:
- ...
- DO ...
- IF unloop exit THEN ...
- LOOP ...
-
-
-
-
- UNMOUNT ( -- )
-
- Vocabulary FORTH
-
- This will prepare a blockstream system to be copied to an other
- device. From all physical blocknumbers contained in the system,
- the number of the first physical block on the actual device
- will be substracted. A later mount will reverse that procedure.
- Always make sure that you are working with MOUNTed systems
- only. Otherwise malfunction is guaranteed. It is not possible
- to doubly UNMOUNT a system.
-
-
-
-
-
- USE ( -- ) \ USE <name>
-
- Vocabulary FORTH
-
- This will open the blockstream with the name <name> for usage.
- A STREAM: structure called USESTREAM will be filled with the
- data of the selected stream. Notice that if a blockstream has
- been created with MAKE, then USE must be supplied additionally.
-
-
-
-
-
- USER ( -- ) \ USER <name>
-
- Vocabulary FORTH
-
- Creates a new USER-variable with the given name.
-
-
-
-
-
- USESTREAM ( -- addr )
-
- Vocabulary BLOCKSTREAM
-
- This is a structure created with STREAM:. It is used by USE.
-
-
-
-
-
- VALUE ( n -- ) \ <n> VALUE <name>
-
- Vocabulary FORTH
-
- Creates a VALUE-type. VALUEs can be read out using <name> and
- be written using 'TO <name>'.
-
- Example:
- 27 VALUE X
- X . --> 27
- 35 TO X
- X . --> 35
-
-
-
-
- VER ( -- n )
-
- Vocabulary FORTH
-
- Gives the BCD representation of the date the kernel has been
- created. E.g. if the kernel has been assembled on 6-12-91 the
- following sequence will yield '19910612':
-
- Example:
- HEX VER .
- \ This makes it possible to compare
- \ different versions using
- \ standard operators like < or >.
-
-
-
-
- VIEW ( -- ) \ view <name>
-
- Vocabulary FORTH
-
- Looks for the source of the word with the given name. The
- appropriate screen will be displaid.
-
- Example:
- view view
-
-
-
-
- VOC' ( -- vocaddr ) \ voc' <vocname>
-
- Vocabulary FORTH
-
- Finds the address of the named vocabulary. This may be very
- usefull together with searching word VOCSEARCH. The returned
- address corresponds to those held in CURRENT or CONTEXT.
-
- Example:
- " DUP" voc' forth vocsearch
-
-
-
-
- VOCABULARY ( -- ) \ VOCABULARY <name>
-
- Vocabulary FORTH
-
- Defines a new vocabulary with the given name. The vocabulary is
- created only, it is not located within search order. The use of
- vocabularies is highly recommended in order to keep the number
- of words in the main vocabulary FORTH as small as possible.
-
-
-
-
-
- VOCS ( -- )
-
- Vocabulary FORTH
-
- Prints a list of all vocabularies.
-
-
-
-
-
- VOCSEARCH ( string vocaddr -- controlword cfa | string -1 )
-
- Vocabulary FORTH
-
- Searches for a word with the name given with the string in the
- specified vocabulary. The address of the vocabulary comes from
- CONTEXT, CURRENT or VOC'. VOCSEARCH is used by (FIND.
-
- Example:
- " DUP" voc' forth vocsearch
-
-
-
-
- WRITESYS ( addr count -- flag )
-
- Vocabulary FORTH
-
- Writes 'count' bytes from the buffer 'addr' in a
- systemdependent manner. WRITESYS calls a routine supplied by
- the loader, which is stored in the USER-variable ^WRITESYS.
-
-
-
-
-
- WRITESYSES ( -- addr )
-
- Vocabulary FORTH
-
- Gives the address of an array, which holds the number and the
- entry-addresses of the loaders I/O-functions to write to a file
- in a system dependent manner. 'WRITESYSES @' gives the number
- of the functions. 'WRITESYSES CELL+ @' is the address of the
- first routine. The routines in this table may not be executed
- from F68K because they need some interfacing provided by
- WRITESYS.
-